* Re: [PATCH 11/X] uprobes: x86: introduce xol_was_trapped()
From: Srikar Dronamraju @ 2011-10-24 14:55 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Peter Zijlstra, Ingo Molnar, Steven Rostedt, Linux-mm,
Arnaldo Carvalho de Melo, Linus Torvalds, Jonathan Corbet,
Masami Hiramatsu, Hugh Dickins, Christoph Hellwig,
Ananth N Mavinakayanahalli, Thomas Gleixner, Andi Kleen,
Andrew Morton, Jim Keniston, Roland McGrath, LKML
In-Reply-To: <20111019215307.GE16395@redhat.com>
> diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
> index 1c30cfd..f0fbdab 100644
> --- a/arch/x86/include/asm/uprobes.h
> +++ b/arch/x86/include/asm/uprobes.h
> @@ -39,6 +39,7 @@ struct uprobe_arch_info {
>
> struct uprobe_task_arch_info {
> unsigned long saved_scratch_register;
> + unsigned long saved_trap_no;
> };
> #else
> struct uprobe_arch_info {};
one nit
I had to add saved_trap_no to #else part (i.e uprobe_arch_info ).
--
Thanks and Regards
Srikar
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH] mmc: mmci: Improve runtime PM support
From: Ulf Hansson @ 2011-10-24 15:25 UTC (permalink / raw)
To: Linus Walleij, Russell King - ARM Linux
Cc: Sebastian Rasmussen, linux-mmc@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <CACRpkdb7FwW=Qa2MiJkbezkBO3F+Y0j6-RWSiL8dfJXkbd4pHw@mail.gmail.com>
Linus Walleij wrote:
> On Mon, Oct 24, 2011 at 1:48 PM, Ulf Hansson <ulf.hansson@stericsson.com> wrote:
>> [Russell]
>>> The MCIPWR signal controls the external power switch. This is the only
>>> signal for it. This is the only connection for it. There is no other
>>> control form for this power switch.
>>>
>> Then we are only left to use the variant struct I believe. In principle, a
>> flag in the variant struct, could indicate whether it is OK to disable the
>> vcore regulator and thus clear the MCIPWR when doing runtime_suspend.
>
> Yep I think the best could be to add some variant named
> bool external_card_power; and then document in the kerneldoc that this
> means the driver can clear MMCIPWR without risk of cutting the power
> to the card.
>
> This should be true for Ux500, U300 and Nomadik (just checked the designs -
> they all have external regulators).
>
Could we assume that all boards which utilizes the ARM PL180 are using
the MMCIPWR register to control power the card? Or should we add a new
amba mmci platform member so this is configurable for each board?
An option could also be if we might want to simplify code to just skip
the entire runtime_suspend|idle|resume function (ie stubb it or
something) for these kind of boards?
What do you prefer?
> So the state save/restore and amba_vcore_disable(adev); should be done
> only for those variants.
>
> However this:
>
> clk_disable(host->clk);
>
> We ought to be able to do for *all* variants, provided we can create
> pm_runtime_get/put and delay properly to cover all bus traffic
> (looks like the patch already does that), plus all the time the card is
> signalling busy. The best I can think of is to just return -EBUSY to runtime
> PM like this:
>
> if ((readl(base + MMCISTATUS) & (MCI_CMDACTIVE | MCI_TXACTIVE| MCI_RXACTIVE))
> return -EBUSY;
>
> Yours,
> Linus Walleij
>
^ permalink raw reply
* Re: [Qemu-devel] [PATCH 35/35] scsi-disk: add scsi-block for device passthrough
From: Kevin Wolf @ 2011-10-24 15:28 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: qemu-devel
In-Reply-To: <1318503845-11473-36-git-send-email-pbonzini@redhat.com>
Am 13.10.2011 13:04, schrieb Paolo Bonzini:
> scsi-block is a new device that supports device passthrough of Linux
> block devices (i.e. /dev/sda, not /dev/sg0). It uses SG_IO for commands
> other than I/O commands, and regular AIO read/writes for I/O commands.
> Besides being simpler to configure (no mapping required to scsi-generic
> device names), this removes the need for a large bounce buffer and,
> in the future, will get scatter/gather support for free from scsi-disk.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This doesn't seem to use much of scsi-disk, so what about exporting
&scsi_disk_reqops and adding a separate file scsi-block.c? Would make
things a bit more symmetrical between scsi-disk and scsi-generic.
Or will future patches add code that depends on internal interfaces of
scsi-disk?
Kevin
^ permalink raw reply
* Re: [Qemu-devel] [Question] dump memory when host pci device is used by guest
From: Dave Anderson @ 2011-10-24 15:25 UTC (permalink / raw)
To: Avi Kivity
Cc: Jan Kiszka, Richard W.M. Jones, qemu-devel, Luiz Capitulino,
KAMEZAWA Hiroyuki
In-Reply-To: <4EA57DD0.6030803@redhat.com>
----- Original Message -----
> On 10/24/2011 04:25 PM, Dave Anderson wrote:
> > > The question is that: 'virsh dump' can not be used when host pci device
> > > is used by guest. We are discussing how to fix the problem. We have determined
> > > that introduce a new monitor command dump. Jan suggested that the core file's
> > > format is gdb standard core format. Does crash support such format? If no,
> > > is it possible to support such format?
> >
> > If you are talking about an ELF core dump of the user-space qemu-kvm process
> > running on the host, then it's certainly not supported.
>
> No, an ELF image of the guest's physical memory.
Well then that should be pretty straight forward to support. Depending upon
how similar it would be to the "standard" kdump ELF format, the only other
issue is how to determine the physical base address at which the kernel is
loaded, in order to be able to translate the mapped kernel-text/static-data
virtual region of the x86_64 arch (the __START_KERNEL_map region).
> > As to whether it's possible, I suppose it could be done if a phyical-memory-read
> > function could be created for it, similar to what I asked about for live analysis
> > of a guest kernel run on/from the KVM host.
>
> We could use the gdb protocol for this. Currently it reads/writes
> virtual memory, but we could extend the gdbserver command to make these
> commands apply to physical memory.
^ permalink raw reply
* [PATCH] wl12xx: keep beacon-filtering enabled during STA operation
From: Arik Nemtsov @ 2011-10-24 15:25 UTC (permalink / raw)
To: linux-wireless; +Cc: Luciano Coelho, Arik Nemtsov
Enable beacon filtering on STA init, and don't disable it when entering
active mode. Otherwise dynamic-PS supports means we receive beacons from
the current AP during any Tx/Rx performed by the driver.
Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
drivers/net/wireless/wl12xx/event.c | 5 -----
drivers/net/wireless/wl12xx/init.c | 12 ++++++------
drivers/net/wireless/wl12xx/ps.c | 5 -----
3 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index e22df6c..00ce794 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -137,11 +137,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
case EVENT_ENTER_POWER_SAVE_SUCCESS:
wlvif->psm_entry_retry = 0;
- /* enable beacon filtering */
- ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
- if (ret < 0)
- break;
-
/*
* BET has only a minor effect in 5GHz and masks
* channel switch IEs, so we only enable BET on 2.4GHz
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index c6084f8..14ff01e 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -254,17 +254,17 @@ static int wl12xx_init_phy_vif_config(struct wl1271 *wl,
return 0;
}
-static int wl1271_init_beacon_filter(struct wl1271 *wl,
- struct wl12xx_vif *wlvif)
+static int wl1271_init_sta_beacon_filter(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif)
{
int ret;
- /* disable beacon filtering at this stage */
- ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false);
+ ret = wl1271_acx_beacon_filter_table(wl, wlvif);
if (ret < 0)
return ret;
- ret = wl1271_acx_beacon_filter_table(wl, wlvif);
+ /* enable beacon filtering */
+ ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
if (ret < 0)
return ret;
@@ -529,7 +529,7 @@ static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
return ret;
/* Beacon filtering */
- ret = wl1271_init_beacon_filter(wl, wlvif);
+ ret = wl1271_init_sta_beacon_filter(wl, wlvif);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 9f4e8c0..a7a1108 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -185,11 +185,6 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
return ret;
}
- /* disable beacon filtering */
- ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false);
- if (ret < 0)
- return ret;
-
ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE);
if (ret < 0)
return ret;
--
1.7.5.4
^ permalink raw reply related
* [PATCH] mmc: mmci: Improve runtime PM support
From: Ulf Hansson @ 2011-10-24 15:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdb7FwW=Qa2MiJkbezkBO3F+Y0j6-RWSiL8dfJXkbd4pHw@mail.gmail.com>
Linus Walleij wrote:
> On Mon, Oct 24, 2011 at 1:48 PM, Ulf Hansson <ulf.hansson@stericsson.com> wrote:
>> [Russell]
>>> The MCIPWR signal controls the external power switch. This is the only
>>> signal for it. This is the only connection for it. There is no other
>>> control form for this power switch.
>>>
>> Then we are only left to use the variant struct I believe. In principle, a
>> flag in the variant struct, could indicate whether it is OK to disable the
>> vcore regulator and thus clear the MCIPWR when doing runtime_suspend.
>
> Yep I think the best could be to add some variant named
> bool external_card_power; and then document in the kerneldoc that this
> means the driver can clear MMCIPWR without risk of cutting the power
> to the card.
>
> This should be true for Ux500, U300 and Nomadik (just checked the designs -
> they all have external regulators).
>
Could we assume that all boards which utilizes the ARM PL180 are using
the MMCIPWR register to control power the card? Or should we add a new
amba mmci platform member so this is configurable for each board?
An option could also be if we might want to simplify code to just skip
the entire runtime_suspend|idle|resume function (ie stubb it or
something) for these kind of boards?
What do you prefer?
> So the state save/restore and amba_vcore_disable(adev); should be done
> only for those variants.
>
> However this:
>
> clk_disable(host->clk);
>
> We ought to be able to do for *all* variants, provided we can create
> pm_runtime_get/put and delay properly to cover all bus traffic
> (looks like the patch already does that), plus all the time the card is
> signalling busy. The best I can think of is to just return -EBUSY to runtime
> PM like this:
>
> if ((readl(base + MMCISTATUS) & (MCI_CMDACTIVE | MCI_TXACTIVE| MCI_RXACTIVE))
> return -EBUSY;
>
> Yours,
> Linus Walleij
>
^ permalink raw reply
* Re: [RFC 1/4] Documentation: devres: add allocation functions to list of supported calls
From: Tejun Heo @ 2011-10-24 15:25 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linux-kernel, linux-arm-kernel, Greg KH, Grant Likely
In-Reply-To: <1319445729-14841-2-git-send-email-w.sang@pengutronix.de>
On Mon, Oct 24, 2011 at 10:42:06AM +0200, Wolfram Sang wrote:
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Tejun Heo <tj@kernel.org>
Thanks.
--
tejun
^ permalink raw reply
* [RFC 1/4] Documentation: devres: add allocation functions to list of supported calls
From: Tejun Heo @ 2011-10-24 15:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1319445729-14841-2-git-send-email-w.sang@pengutronix.de>
On Mon, Oct 24, 2011 at 10:42:06AM +0200, Wolfram Sang wrote:
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Tejun Heo <tj@kernel.org>
Thanks.
--
tejun
^ permalink raw reply
* Re: [PATCH V2 1/2] ARM: EXYNOS4: Add SPI support
From: Kukjin Kim @ 2011-10-24 15:24 UTC (permalink / raw)
To: Kukjin Kim
Cc: 'Padmavathi Venna', padma.kvr, linux-samsung-soc,
linux-arm-kernel, linux, ben-linux
In-Reply-To: <038e01cc872f$a95a93c0$fc0fbb40$%kim@samsung.com>
On 10/10/11 11:33, Kukjin Kim wrote:
> Padmavathi Venna wrote:
>>
>> Define SPI platform devices.
>> Register SPI bus clock with clkdev using generic
>> connection id.
>>
>
> I can't see your second patch 'SPI: EXYNOS4: Enable the SPI driver for
> EXYNOS4'. Probably you think it should be handled by spi side, Grant. Yes
> right. But when you submit patch set is related to each subsystem such as
> arch/arm/ and drivers/, please adding regarding maintainers on your patch
> set. So they can know whether necessity of talking to each other is required
> or not if there are dependencies. In this case, I need to know the progress
> of driver/spi side.
>
>> Signed-off-by: Padmavathi Venna<padma.v@samsung.com>
>> ---
>> arch/arm/mach-exynos4/Kconfig | 1 +
>> arch/arm/mach-exynos4/Makefile | 1 +
>> arch/arm/mach-exynos4/clock.c | 82 +++++---
>> arch/arm/mach-exynos4/dev-spi.c | 225
>> ++++++++++++++++++++++
>> arch/arm/mach-exynos4/include/mach/irqs.h | 3 +
>> arch/arm/mach-exynos4/include/mach/map.h | 3 +
>> arch/arm/mach-exynos4/include/mach/spi-clocks.h | 16 ++
>> arch/arm/plat-samsung/include/plat/devs.h | 3 +
>> arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 1 +
>> 9 files changed, 305 insertions(+), 30 deletions(-)
>> create mode 100644 arch/arm/mach-exynos4/dev-spi.c
>> create mode 100644 arch/arm/mach-exynos4/include/mach/spi-clocks.h
>>
>> diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
>> index d0491c2..96b2511 100644
>> --- a/arch/arm/mach-exynos4/Kconfig
>> +++ b/arch/arm/mach-exynos4/Kconfig
>> @@ -154,6 +154,7 @@ config MACH_SMDKV310
>> select EXYNOS4_SETUP_KEYPAD
>> select EXYNOS4_SETUP_SDHCI
>> select EXYNOS4_SETUP_USB_PHY
>> + select S3C64XX_DEV_SPI
>
> Hmm...if possible, please keep the alphabetical ordering here and I wonder
> S3C64XX_DEV_SPI is proper name......
>
>> help
>> Machine support for Samsung SMDKV310
>>
>> diff --git a/arch/arm/mach-exynos4/Makefile
> b/arch/arm/mach-exynos4/Makefile
>> index e19cd12..7376869 100644
>> --- a/arch/arm/mach-exynos4/Makefile
>> +++ b/arch/arm/mach-exynos4/Makefile
>> @@ -43,6 +43,7 @@ obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-
>> ahci.o
>> obj-$(CONFIG_EXYNOS4_DEV_PD) += dev-pd.o
>> obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o
>> obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o
>> +obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
>>
>> obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o
>> obj-$(CONFIG_EXYNOS4_SETUP_FIMD0) += setup-fimd0.o
>> diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
>> index a25c818..2497176 100644
>> --- a/arch/arm/mach-exynos4/clock.c
>> +++ b/arch/arm/mach-exynos4/clock.c
>> @@ -1152,36 +1152,6 @@ static struct clksrc_clk clksrcs[] = {
>> .reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4
> },
>> }, {
>> .clk = {
>> - .name = "sclk_spi",
>> - .devname = "s3c64xx-spi.0",
>> - .enable = exynos4_clksrc_mask_peril1_ctrl,
>> - .ctrlbit = (1<< 16),
>> - },
>> - .sources =&clkset_group,
>> - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size =
> 4 },
>> - .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4
> },
>> - }, {
>> - .clk = {
>> - .name = "sclk_spi",
>> - .devname = "s3c64xx-spi.1",
>> - .enable = exynos4_clksrc_mask_peril1_ctrl,
>> - .ctrlbit = (1<< 20),
>> - },
>> - .sources =&clkset_group,
>> - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size =
> 4 },
>> - .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size =
> 4 },
>> - }, {
>> - .clk = {
>> - .name = "sclk_spi",
>> - .devname = "s3c64xx-spi.2",
>> - .enable = exynos4_clksrc_mask_peril1_ctrl,
>> - .ctrlbit = (1<< 24),
>> - },
>> - .sources =&clkset_group,
>> - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size =
> 4 },
>> - .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4
> },
>> - }, {
>> - .clk = {
>> .name = "sclk_fimg2d",
>> },
>> .sources =&clkset_mout_g2d,
>> @@ -1242,6 +1212,53 @@ static struct clksrc_clk clksrcs[] = {
>> }
>> };
>>
>> +static struct clksrc_clk sclk_spi0 = {
>> + .clk = {
>> + .name = "sclk_spi",
>> + .devname = "s3c64xx-spi.0",
>> + .enable = exynos4_clksrc_mask_peril1_ctrl,
>> + .ctrlbit = (1<< 16),
>> + },
>> + .sources =&clkset_group,
>> + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
>> + .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
>> +};
>> +
>> +static struct clksrc_clk sclk_spi1 = {
>> + .clk = {
>> + .name = "sclk_spi",
>> + .devname = "s3c64xx-spi.1",
>> + .enable = exynos4_clksrc_mask_peril1_ctrl,
>> + .ctrlbit = (1<< 20),
>> + },
>> + .sources =&clkset_group,
>> + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
>> + .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
>> +};
>> +static struct clksrc_clk sclk_spi2 = {
>> + .clk = {
>> + .name = "sclk_spi",
>> + .devname = "s3c64xx-spi.2",
>> + .enable = exynos4_clksrc_mask_peril1_ctrl,
>> + .ctrlbit = (1<< 24),
>> + },
>> + .sources =&clkset_group,
>> + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
>> + .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
>> +};
>> +
>> +static struct clk_lookup clk_lookup_table[] = {
>> + CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0",&sclk_spi0.clk),
>> + CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0",&sclk_spi1.clk),
>> + CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0",&sclk_spi2.clk),
>
> Yes, as you said, firstly your CLKDEV_INIT patch is needed before this. So I
> need to think this can be sent to upstream in this time or next time even
> though this patch is good.
>
>> +};
>> +
>> +static struct clksrc_clk *clksrc_cdev[] = {
>> + &sclk_spi0,
>> + &sclk_spi1,
>> + &sclk_spi2,
>> +};
>> +
>> /* Clock initialization code */
>> static struct clksrc_clk *sysclks[] = {
>> &clk_mout_apll,
>> @@ -1480,6 +1497,9 @@ void __init exynos4_register_clocks(void)
>> for (ptr = 0; ptr< ARRAY_SIZE(sysclks); ptr++)
>> s3c_register_clksrc(sysclks[ptr], 1);
>>
>> + for (ptr = 0; ptr< ARRAY_SIZE(clksrc_cdev); ptr++)
>> + s3c_register_clksrc(clksrc_cdev[ptr], 1);
>> +
>> for (ptr = 0; ptr< ARRAY_SIZE(sclk_tv); ptr++)
>> s3c_register_clksrc(sclk_tv[ptr], 1);
>>
>> @@ -1493,4 +1513,6 @@ void __init exynos4_register_clocks(void)
>> s3c24xx_register_clock(&dummy_apb_pclk);
>>
>> s3c_pwmclk_init();
>> +
>> + clkdev_add_table(clk_lookup_table, ARRAY_SIZE(clk_lookup_table));
>> }
>> diff --git a/arch/arm/mach-exynos4/dev-spi.c
> b/arch/arm/mach-exynos4/dev-spi.c
>> new file mode 100644
>> index 0000000..0c9704d
>> --- /dev/null
>> +++ b/arch/arm/mach-exynos4/dev-spi.c
>> @@ -0,0 +1,225 @@
>> +/* linux/arch/arm/mach-exynos4/dev-spi.c
>> + *
>> + * Copyright (C) 2011 Samsung Electronics Co. Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include<linux/platform_device.h>
>> +#include<linux/dma-mapping.h>
>> +#include<linux/gpio.h>
>> +
>> +#include<mach/dma.h>
>> +#include<mach/map.h>
>> +#include<mach/irqs.h>
>> +#include<mach/spi-clocks.h>
>> +
>> +#include<plat/s3c64xx-spi.h>
>> +#include<plat/gpio-cfg.h>
>> +
>> +/* SPI Controller platform_devices */
>> +
>> +/* Since we emulate multi-cs capability, we do not touch the CS.
>
> According to coding style(multi-line comments) ......
>
> /*
> * foo
> * foo
> */
>
> So,
>
> +/*
> + * Since we emulate multi-cs capability, we do not touch the CS.
>
>
>> + * The emulated CS is toggled by board specific mechanism, as it can
>> + * be either some immediate GPIO or some signal out of some other
>> + * chip in between ... or some yet another way.
>> + * We simply do not assume anything about CS.
>> + */
>> +static int exynos4_spi_cfg_gpio(struct platform_device *pdev)
>> +{
>> + switch (pdev->id) {
>> + case 0:
>> + s3c_gpio_cfgpin(EXYNOS4_GPB(0), S3C_GPIO_SFN(2));
>> + s3c_gpio_setpull(EXYNOS4_GPB(0), S3C_GPIO_PULL_UP);
>> + s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
>> + S3C_GPIO_SFN(2),
>> S3C_GPIO_PULL_UP);
>> + break;
>> +
>> + case 1:
>> + s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_SFN(2));
>> + s3c_gpio_setpull(EXYNOS4_GPB(4), S3C_GPIO_PULL_UP);
>> + s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2,
>> + S3C_GPIO_SFN(2),
>> S3C_GPIO_PULL_UP);
>> + break;
>> +
>> + case 2:
>> + s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_SFN(5));
>> + s3c_gpio_setpull(EXYNOS4_GPC1(1), S3C_GPIO_PULL_UP);
>> + s3c_gpio_cfgall_range(EXYNOS4_GPC1(3), 2,
>> + S3C_GPIO_SFN(5),
>> S3C_GPIO_PULL_UP);
>> + break;
>> +
>> + default:
>> + dev_err(&pdev->dev, "Invalid SPI Controller number!");
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static struct resource exynos4_spi0_resource[] = {
>> + [0] = {
>> + .start = EXYNOS4_PA_SPI0,
>> + .end = EXYNOS4_PA_SPI0 + 0x100 - 1,
>
> Please use SZ_256 instead of 0x100.
>
>> + .flags = IORESOURCE_MEM,
>> + },
>
> DEFINE_RES_MEM(...)
>
>> + [1] = {
>> + .start = DMACH_SPI0_TX,
>> + .end = DMACH_SPI0_TX,
>> + .flags = IORESOURCE_DMA,
>> + },
>
> DEFINE_RES_DMA(...)
>
>> + [2] = {
>> + .start = DMACH_SPI0_RX,
>> + .end = DMACH_SPI0_RX,
>> + .flags = IORESOURCE_DMA,
>> + },
>
> Same as above.
>
>> + [3] = {
>> + .start = IRQ_SPI0,
>> + .end = IRQ_SPI0,
>> + .flags = IORESOURCE_IRQ,
>> + },
>
> DEFINE_RES_IRQ(...)
>
>> +};
>> +
>> +static struct s3c64xx_spi_info exynos4_spi0_pdata = {
>> + .cfg_gpio = exynos4_spi_cfg_gpio,
>> + .fifo_lvl_mask = 0x1ff,
>> + .rx_lvl_offset = 15,
>> + .high_speed = 1,
>> + .clk_from_cmu = true,
>> + .tx_st_done = 25,
>
> I don't think we need all exynos4_spi0_pdata, exynos4_spi1_pdata and
> exynos4_spi2_pdata because only its fifo_lvl_mask is different with each
> other. As you know it can be added when it is initialized.
>
>> +};
>> +
>> +static u64 spi_dmamask = DMA_BIT_MASK(32);
>> +
>> +struct platform_device exynos4_device_spi0 = {
>> + .name = "s3c64xx-spi",
>> + .id = 0,
>> + .num_resources = ARRAY_SIZE(exynos4_spi0_resource),
>> + .resource = exynos4_spi0_resource,
>> + .dev = {
>> + .dma_mask =&spi_dmamask,
>> + .coherent_dma_mask = DMA_BIT_MASK(32),
>> + .platform_data =&exynos4_spi0_pdata,
>> + },
>> +};
>> +
>> +static struct resource exynos4_spi1_resource[] = {
>> + [0] = {
>> + .start = EXYNOS4_PA_SPI1,
>> + .end = EXYNOS4_PA_SPI1 + 0x100 - 1,
>> + .flags = IORESOURCE_MEM,
>> + },
>> + [1] = {
>> + .start = DMACH_SPI1_TX,
>> + .end = DMACH_SPI1_TX,
>> + .flags = IORESOURCE_DMA,
>> + },
>> + [2] = {
>> + .start = DMACH_SPI1_RX,
>> + .end = DMACH_SPI1_RX,
>> + .flags = IORESOURCE_DMA,
>> + },
>> + [3] = {
>> + .start = IRQ_SPI1,
>> + .end = IRQ_SPI1,
>> + .flags = IORESOURCE_IRQ,
>> + },
>> +};
>> +
>> +static struct s3c64xx_spi_info exynos4_spi1_pdata = {
>> + .cfg_gpio = exynos4_spi_cfg_gpio,
>> + .fifo_lvl_mask = 0x7f,
>> + .rx_lvl_offset = 15,
>> + .high_speed = 1,
>> + .clk_from_cmu = true,
>> + .tx_st_done = 25,
>> +};
>> +
>> +struct platform_device exynos4_device_spi1 = {
>> + .name = "s3c64xx-spi",
>> + .id = 1,
>> + .num_resources = ARRAY_SIZE(exynos4_spi1_resource),
>> + .resource = exynos4_spi1_resource,
>> + .dev = {
>> + .dma_mask =&spi_dmamask,
>> + .coherent_dma_mask = DMA_BIT_MASK(32),
>> + .platform_data =&exynos4_spi1_pdata,
>> + },
>> +};
>> +
>> +static struct resource exynos4_spi2_resource[] = {
>> + [0] = {
>> + .start = EXYNOS4_PA_SPI2,
>> + .end = EXYNOS4_PA_SPI2 + 0x100 - 1,
>> + .flags = IORESOURCE_MEM,
>> + },
>> + [1] = {
>> + .start = DMACH_SPI2_TX,
>> + .end = DMACH_SPI2_TX,
>> + .flags = IORESOURCE_DMA,
>> + },
>> + [2] = {
>> + .start = DMACH_SPI2_RX,
>> + .end = DMACH_SPI2_RX,
>> + .flags = IORESOURCE_DMA,
>> + },
>> + [3] = {
>> + .start = IRQ_SPI2,
>> + .end = IRQ_SPI2,
>> + .flags = IORESOURCE_IRQ,
>> + },
>> +};
>> +
>> +static struct s3c64xx_spi_info exynos4_spi2_pdata = {
>> + .cfg_gpio = exynos4_spi_cfg_gpio,
>> + .fifo_lvl_mask = 0x7f,
>> + .rx_lvl_offset = 15,
>> + .high_speed = 1,
>> + .clk_from_cmu = true,
>> + .tx_st_done = 25,
>> +};
>> +
>> +struct platform_device exynos4_device_spi2 = {
>> + .name = "s3c64xx-spi",
>> + .id = 2,
>> + .num_resources = ARRAY_SIZE(exynos4_spi2_resource),
>> + .resource = exynos4_spi2_resource,
>> + .dev = {
>> + .dma_mask =&spi_dmamask,
>> + .coherent_dma_mask = DMA_BIT_MASK(32),
>> + .platform_data =&exynos4_spi2_pdata,
>> + },
>> +};
>> +
>> +void __init exynos4_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
>> +{
>> + struct s3c64xx_spi_info *pd;
>> +
>> + /* Reject invalid configuration */
>> + if (!num_cs || src_clk_nr< 0
>> + || src_clk_nr> EXYNOS4_SPI_SRCCLK_SCLK) {
>> + printk(KERN_ERR "%s: Invalid SPI configuration\n",
> __func__);
>> + return;
>> + }
>> +
>> + switch (cntrlr) {
>> + case 0:
>> + pd =&exynos4_spi0_pdata;
>> + break;
>> + case 1:
>> + pd =&exynos4_spi1_pdata;
>> + break;
>> + case 2:
>> + pd =&exynos4_spi2_pdata;
>> + break;
>> + default:
>> + printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
>> + __func__, cntrlr);
>> + return;
>> + }
>> +
>> + pd->num_cs = num_cs;
>> + pd->src_clk_nr = src_clk_nr;
>> +}
>
> I think you can consolidate dev-spi.c in mach-s3c64xx directory. How about
> to move them into plat-samsung/devs.c?
>
> Please refer to next/topic-plat-samsung-devs branch in my tree.
>
>> diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-
>> exynos4/include/mach/irqs.h
>> index 62093b9..a9f0341 100644
>> --- a/arch/arm/mach-exynos4/include/mach/irqs.h
>> +++ b/arch/arm/mach-exynos4/include/mach/irqs.h
>> @@ -70,6 +70,9 @@
>> #define IRQ_IIC5 IRQ_SPI(63)
>> #define IRQ_IIC6 IRQ_SPI(64)
>> #define IRQ_IIC7 IRQ_SPI(65)
>> +#define IRQ_SPI0 IRQ_SPI(66)
>> +#define IRQ_SPI1 IRQ_SPI(67)
>> +#define IRQ_SPI2 IRQ_SPI(68)
>>
>> #define IRQ_USB_HOST IRQ_SPI(70)
>> #define IRQ_USB_HSOTG IRQ_SPI(71)
>> diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-
>> exynos4/include/mach/map.h
>> index 1bea7d1..8dd509e 100644
>> --- a/arch/arm/mach-exynos4/include/mach/map.h
>> +++ b/arch/arm/mach-exynos4/include/mach/map.h
>> @@ -88,6 +88,9 @@
>> #define EXYNOS4_PA_SYSMMU_TV 0x12E20000
>> #define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000
>> #define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000
>> +#define EXYNOS4_PA_SPI0 0x13920000
>> +#define EXYNOS4_PA_SPI1 0x13930000
>> +#define EXYNOS4_PA_SPI2 0x13940000
>>
>> #define EXYNOS4_PA_GPIO1 0x11400000
>> #define EXYNOS4_PA_GPIO2 0x11000000
>> diff --git a/arch/arm/mach-exynos4/include/mach/spi-clocks.h
> b/arch/arm/mach-
>> exynos4/include/mach/spi-clocks.h
>> new file mode 100644
>> index 0000000..576efdf
>> --- /dev/null
>> +++ b/arch/arm/mach-exynos4/include/mach/spi-clocks.h
>> @@ -0,0 +1,16 @@
>> +/* linux/arch/arm/mach-exynos4/include/mach/spi-clocks.h
>> + *
>> + * Copyright (C) 2011 Samsung Electronics Co. Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __ASM_ARCH_SPI_CLKS_H
>> +#define __ASM_ARCH_SPI_CLKS_H __FILE__
>> +
>> +/* Must source from SCLK_SPI */
>> +#define EXYNOS4_SPI_SRCCLK_SCLK 0
>> +
>> +#endif /* __ASM_ARCH_SPI_CLKS_H */
>> diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-
>> samsung/include/plat/devs.h
>> index ee5014a..7949131 100644
>> --- a/arch/arm/plat-samsung/include/plat/devs.h
>> +++ b/arch/arm/plat-samsung/include/plat/devs.h
>> @@ -84,6 +84,9 @@ extern struct platform_device s5pv210_device_spi0;
>> extern struct platform_device s5pv210_device_spi1;
>> extern struct platform_device s5p64x0_device_spi0;
>> extern struct platform_device s5p64x0_device_spi1;
>> +extern struct platform_device exynos4_device_spi0;
>> +extern struct platform_device exynos4_device_spi1;
>> +extern struct platform_device exynos4_device_spi2;
>>
>> extern struct platform_device s3c_device_hwmon;
>>
>> diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
> b/arch/arm/plat-
>> samsung/include/plat/s3c64xx-spi.h
>> index c3d82a5..1ec1ea3 100644
>> --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
>> +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
>> @@ -69,5 +69,6 @@ extern void s3c64xx_spi_set_info(int cntrlr, int
> src_clk_nr, int
>> num_cs);
>> extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
>> extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
>> extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
>> +extern void exynos4_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
>>
>> #endif /* __S3C64XX_PLAT_SPI_H */
>> --
>> 1.7.4.4
Hi Padmavathi,
As you know, this needs to re-submit/re-work. Could you please do it as
soon as possible with your other SPI clkdev patches?
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH V2 1/2] ARM: EXYNOS4: Add SPI support
From: Kukjin Kim @ 2011-10-24 15:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <038e01cc872f$a95a93c0$fc0fbb40$%kim@samsung.com>
On 10/10/11 11:33, Kukjin Kim wrote:
> Padmavathi Venna wrote:
>>
>> Define SPI platform devices.
>> Register SPI bus clock with clkdev using generic
>> connection id.
>>
>
> I can't see your second patch 'SPI: EXYNOS4: Enable the SPI driver for
> EXYNOS4'. Probably you think it should be handled by spi side, Grant. Yes
> right. But when you submit patch set is related to each subsystem such as
> arch/arm/ and drivers/, please adding regarding maintainers on your patch
> set. So they can know whether necessity of talking to each other is required
> or not if there are dependencies. In this case, I need to know the progress
> of driver/spi side.
>
>> Signed-off-by: Padmavathi Venna<padma.v@samsung.com>
>> ---
>> arch/arm/mach-exynos4/Kconfig | 1 +
>> arch/arm/mach-exynos4/Makefile | 1 +
>> arch/arm/mach-exynos4/clock.c | 82 +++++---
>> arch/arm/mach-exynos4/dev-spi.c | 225
>> ++++++++++++++++++++++
>> arch/arm/mach-exynos4/include/mach/irqs.h | 3 +
>> arch/arm/mach-exynos4/include/mach/map.h | 3 +
>> arch/arm/mach-exynos4/include/mach/spi-clocks.h | 16 ++
>> arch/arm/plat-samsung/include/plat/devs.h | 3 +
>> arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 1 +
>> 9 files changed, 305 insertions(+), 30 deletions(-)
>> create mode 100644 arch/arm/mach-exynos4/dev-spi.c
>> create mode 100644 arch/arm/mach-exynos4/include/mach/spi-clocks.h
>>
>> diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
>> index d0491c2..96b2511 100644
>> --- a/arch/arm/mach-exynos4/Kconfig
>> +++ b/arch/arm/mach-exynos4/Kconfig
>> @@ -154,6 +154,7 @@ config MACH_SMDKV310
>> select EXYNOS4_SETUP_KEYPAD
>> select EXYNOS4_SETUP_SDHCI
>> select EXYNOS4_SETUP_USB_PHY
>> + select S3C64XX_DEV_SPI
>
> Hmm...if possible, please keep the alphabetical ordering here and I wonder
> S3C64XX_DEV_SPI is proper name......
>
>> help
>> Machine support for Samsung SMDKV310
>>
>> diff --git a/arch/arm/mach-exynos4/Makefile
> b/arch/arm/mach-exynos4/Makefile
>> index e19cd12..7376869 100644
>> --- a/arch/arm/mach-exynos4/Makefile
>> +++ b/arch/arm/mach-exynos4/Makefile
>> @@ -43,6 +43,7 @@ obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-
>> ahci.o
>> obj-$(CONFIG_EXYNOS4_DEV_PD) += dev-pd.o
>> obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o
>> obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o
>> +obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
>>
>> obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o
>> obj-$(CONFIG_EXYNOS4_SETUP_FIMD0) += setup-fimd0.o
>> diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
>> index a25c818..2497176 100644
>> --- a/arch/arm/mach-exynos4/clock.c
>> +++ b/arch/arm/mach-exynos4/clock.c
>> @@ -1152,36 +1152,6 @@ static struct clksrc_clk clksrcs[] = {
>> .reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4
> },
>> }, {
>> .clk = {
>> - .name = "sclk_spi",
>> - .devname = "s3c64xx-spi.0",
>> - .enable = exynos4_clksrc_mask_peril1_ctrl,
>> - .ctrlbit = (1<< 16),
>> - },
>> - .sources =&clkset_group,
>> - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size =
> 4 },
>> - .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4
> },
>> - }, {
>> - .clk = {
>> - .name = "sclk_spi",
>> - .devname = "s3c64xx-spi.1",
>> - .enable = exynos4_clksrc_mask_peril1_ctrl,
>> - .ctrlbit = (1<< 20),
>> - },
>> - .sources =&clkset_group,
>> - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size =
> 4 },
>> - .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size =
> 4 },
>> - }, {
>> - .clk = {
>> - .name = "sclk_spi",
>> - .devname = "s3c64xx-spi.2",
>> - .enable = exynos4_clksrc_mask_peril1_ctrl,
>> - .ctrlbit = (1<< 24),
>> - },
>> - .sources =&clkset_group,
>> - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size =
> 4 },
>> - .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4
> },
>> - }, {
>> - .clk = {
>> .name = "sclk_fimg2d",
>> },
>> .sources =&clkset_mout_g2d,
>> @@ -1242,6 +1212,53 @@ static struct clksrc_clk clksrcs[] = {
>> }
>> };
>>
>> +static struct clksrc_clk sclk_spi0 = {
>> + .clk = {
>> + .name = "sclk_spi",
>> + .devname = "s3c64xx-spi.0",
>> + .enable = exynos4_clksrc_mask_peril1_ctrl,
>> + .ctrlbit = (1<< 16),
>> + },
>> + .sources =&clkset_group,
>> + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
>> + .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
>> +};
>> +
>> +static struct clksrc_clk sclk_spi1 = {
>> + .clk = {
>> + .name = "sclk_spi",
>> + .devname = "s3c64xx-spi.1",
>> + .enable = exynos4_clksrc_mask_peril1_ctrl,
>> + .ctrlbit = (1<< 20),
>> + },
>> + .sources =&clkset_group,
>> + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
>> + .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
>> +};
>> +static struct clksrc_clk sclk_spi2 = {
>> + .clk = {
>> + .name = "sclk_spi",
>> + .devname = "s3c64xx-spi.2",
>> + .enable = exynos4_clksrc_mask_peril1_ctrl,
>> + .ctrlbit = (1<< 24),
>> + },
>> + .sources =&clkset_group,
>> + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
>> + .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
>> +};
>> +
>> +static struct clk_lookup clk_lookup_table[] = {
>> + CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0",&sclk_spi0.clk),
>> + CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0",&sclk_spi1.clk),
>> + CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0",&sclk_spi2.clk),
>
> Yes, as you said, firstly your CLKDEV_INIT patch is needed before this. So I
> need to think this can be sent to upstream in this time or next time even
> though this patch is good.
>
>> +};
>> +
>> +static struct clksrc_clk *clksrc_cdev[] = {
>> + &sclk_spi0,
>> + &sclk_spi1,
>> + &sclk_spi2,
>> +};
>> +
>> /* Clock initialization code */
>> static struct clksrc_clk *sysclks[] = {
>> &clk_mout_apll,
>> @@ -1480,6 +1497,9 @@ void __init exynos4_register_clocks(void)
>> for (ptr = 0; ptr< ARRAY_SIZE(sysclks); ptr++)
>> s3c_register_clksrc(sysclks[ptr], 1);
>>
>> + for (ptr = 0; ptr< ARRAY_SIZE(clksrc_cdev); ptr++)
>> + s3c_register_clksrc(clksrc_cdev[ptr], 1);
>> +
>> for (ptr = 0; ptr< ARRAY_SIZE(sclk_tv); ptr++)
>> s3c_register_clksrc(sclk_tv[ptr], 1);
>>
>> @@ -1493,4 +1513,6 @@ void __init exynos4_register_clocks(void)
>> s3c24xx_register_clock(&dummy_apb_pclk);
>>
>> s3c_pwmclk_init();
>> +
>> + clkdev_add_table(clk_lookup_table, ARRAY_SIZE(clk_lookup_table));
>> }
>> diff --git a/arch/arm/mach-exynos4/dev-spi.c
> b/arch/arm/mach-exynos4/dev-spi.c
>> new file mode 100644
>> index 0000000..0c9704d
>> --- /dev/null
>> +++ b/arch/arm/mach-exynos4/dev-spi.c
>> @@ -0,0 +1,225 @@
>> +/* linux/arch/arm/mach-exynos4/dev-spi.c
>> + *
>> + * Copyright (C) 2011 Samsung Electronics Co. Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include<linux/platform_device.h>
>> +#include<linux/dma-mapping.h>
>> +#include<linux/gpio.h>
>> +
>> +#include<mach/dma.h>
>> +#include<mach/map.h>
>> +#include<mach/irqs.h>
>> +#include<mach/spi-clocks.h>
>> +
>> +#include<plat/s3c64xx-spi.h>
>> +#include<plat/gpio-cfg.h>
>> +
>> +/* SPI Controller platform_devices */
>> +
>> +/* Since we emulate multi-cs capability, we do not touch the CS.
>
> According to coding style(multi-line comments) ......
>
> /*
> * foo
> * foo
> */
>
> So,
>
> +/*
> + * Since we emulate multi-cs capability, we do not touch the CS.
>
>
>> + * The emulated CS is toggled by board specific mechanism, as it can
>> + * be either some immediate GPIO or some signal out of some other
>> + * chip in between ... or some yet another way.
>> + * We simply do not assume anything about CS.
>> + */
>> +static int exynos4_spi_cfg_gpio(struct platform_device *pdev)
>> +{
>> + switch (pdev->id) {
>> + case 0:
>> + s3c_gpio_cfgpin(EXYNOS4_GPB(0), S3C_GPIO_SFN(2));
>> + s3c_gpio_setpull(EXYNOS4_GPB(0), S3C_GPIO_PULL_UP);
>> + s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
>> + S3C_GPIO_SFN(2),
>> S3C_GPIO_PULL_UP);
>> + break;
>> +
>> + case 1:
>> + s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_SFN(2));
>> + s3c_gpio_setpull(EXYNOS4_GPB(4), S3C_GPIO_PULL_UP);
>> + s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2,
>> + S3C_GPIO_SFN(2),
>> S3C_GPIO_PULL_UP);
>> + break;
>> +
>> + case 2:
>> + s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_SFN(5));
>> + s3c_gpio_setpull(EXYNOS4_GPC1(1), S3C_GPIO_PULL_UP);
>> + s3c_gpio_cfgall_range(EXYNOS4_GPC1(3), 2,
>> + S3C_GPIO_SFN(5),
>> S3C_GPIO_PULL_UP);
>> + break;
>> +
>> + default:
>> + dev_err(&pdev->dev, "Invalid SPI Controller number!");
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static struct resource exynos4_spi0_resource[] = {
>> + [0] = {
>> + .start = EXYNOS4_PA_SPI0,
>> + .end = EXYNOS4_PA_SPI0 + 0x100 - 1,
>
> Please use SZ_256 instead of 0x100.
>
>> + .flags = IORESOURCE_MEM,
>> + },
>
> DEFINE_RES_MEM(...)
>
>> + [1] = {
>> + .start = DMACH_SPI0_TX,
>> + .end = DMACH_SPI0_TX,
>> + .flags = IORESOURCE_DMA,
>> + },
>
> DEFINE_RES_DMA(...)
>
>> + [2] = {
>> + .start = DMACH_SPI0_RX,
>> + .end = DMACH_SPI0_RX,
>> + .flags = IORESOURCE_DMA,
>> + },
>
> Same as above.
>
>> + [3] = {
>> + .start = IRQ_SPI0,
>> + .end = IRQ_SPI0,
>> + .flags = IORESOURCE_IRQ,
>> + },
>
> DEFINE_RES_IRQ(...)
>
>> +};
>> +
>> +static struct s3c64xx_spi_info exynos4_spi0_pdata = {
>> + .cfg_gpio = exynos4_spi_cfg_gpio,
>> + .fifo_lvl_mask = 0x1ff,
>> + .rx_lvl_offset = 15,
>> + .high_speed = 1,
>> + .clk_from_cmu = true,
>> + .tx_st_done = 25,
>
> I don't think we need all exynos4_spi0_pdata, exynos4_spi1_pdata and
> exynos4_spi2_pdata because only its fifo_lvl_mask is different with each
> other. As you know it can be added when it is initialized.
>
>> +};
>> +
>> +static u64 spi_dmamask = DMA_BIT_MASK(32);
>> +
>> +struct platform_device exynos4_device_spi0 = {
>> + .name = "s3c64xx-spi",
>> + .id = 0,
>> + .num_resources = ARRAY_SIZE(exynos4_spi0_resource),
>> + .resource = exynos4_spi0_resource,
>> + .dev = {
>> + .dma_mask =&spi_dmamask,
>> + .coherent_dma_mask = DMA_BIT_MASK(32),
>> + .platform_data =&exynos4_spi0_pdata,
>> + },
>> +};
>> +
>> +static struct resource exynos4_spi1_resource[] = {
>> + [0] = {
>> + .start = EXYNOS4_PA_SPI1,
>> + .end = EXYNOS4_PA_SPI1 + 0x100 - 1,
>> + .flags = IORESOURCE_MEM,
>> + },
>> + [1] = {
>> + .start = DMACH_SPI1_TX,
>> + .end = DMACH_SPI1_TX,
>> + .flags = IORESOURCE_DMA,
>> + },
>> + [2] = {
>> + .start = DMACH_SPI1_RX,
>> + .end = DMACH_SPI1_RX,
>> + .flags = IORESOURCE_DMA,
>> + },
>> + [3] = {
>> + .start = IRQ_SPI1,
>> + .end = IRQ_SPI1,
>> + .flags = IORESOURCE_IRQ,
>> + },
>> +};
>> +
>> +static struct s3c64xx_spi_info exynos4_spi1_pdata = {
>> + .cfg_gpio = exynos4_spi_cfg_gpio,
>> + .fifo_lvl_mask = 0x7f,
>> + .rx_lvl_offset = 15,
>> + .high_speed = 1,
>> + .clk_from_cmu = true,
>> + .tx_st_done = 25,
>> +};
>> +
>> +struct platform_device exynos4_device_spi1 = {
>> + .name = "s3c64xx-spi",
>> + .id = 1,
>> + .num_resources = ARRAY_SIZE(exynos4_spi1_resource),
>> + .resource = exynos4_spi1_resource,
>> + .dev = {
>> + .dma_mask =&spi_dmamask,
>> + .coherent_dma_mask = DMA_BIT_MASK(32),
>> + .platform_data =&exynos4_spi1_pdata,
>> + },
>> +};
>> +
>> +static struct resource exynos4_spi2_resource[] = {
>> + [0] = {
>> + .start = EXYNOS4_PA_SPI2,
>> + .end = EXYNOS4_PA_SPI2 + 0x100 - 1,
>> + .flags = IORESOURCE_MEM,
>> + },
>> + [1] = {
>> + .start = DMACH_SPI2_TX,
>> + .end = DMACH_SPI2_TX,
>> + .flags = IORESOURCE_DMA,
>> + },
>> + [2] = {
>> + .start = DMACH_SPI2_RX,
>> + .end = DMACH_SPI2_RX,
>> + .flags = IORESOURCE_DMA,
>> + },
>> + [3] = {
>> + .start = IRQ_SPI2,
>> + .end = IRQ_SPI2,
>> + .flags = IORESOURCE_IRQ,
>> + },
>> +};
>> +
>> +static struct s3c64xx_spi_info exynos4_spi2_pdata = {
>> + .cfg_gpio = exynos4_spi_cfg_gpio,
>> + .fifo_lvl_mask = 0x7f,
>> + .rx_lvl_offset = 15,
>> + .high_speed = 1,
>> + .clk_from_cmu = true,
>> + .tx_st_done = 25,
>> +};
>> +
>> +struct platform_device exynos4_device_spi2 = {
>> + .name = "s3c64xx-spi",
>> + .id = 2,
>> + .num_resources = ARRAY_SIZE(exynos4_spi2_resource),
>> + .resource = exynos4_spi2_resource,
>> + .dev = {
>> + .dma_mask =&spi_dmamask,
>> + .coherent_dma_mask = DMA_BIT_MASK(32),
>> + .platform_data =&exynos4_spi2_pdata,
>> + },
>> +};
>> +
>> +void __init exynos4_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
>> +{
>> + struct s3c64xx_spi_info *pd;
>> +
>> + /* Reject invalid configuration */
>> + if (!num_cs || src_clk_nr< 0
>> + || src_clk_nr> EXYNOS4_SPI_SRCCLK_SCLK) {
>> + printk(KERN_ERR "%s: Invalid SPI configuration\n",
> __func__);
>> + return;
>> + }
>> +
>> + switch (cntrlr) {
>> + case 0:
>> + pd =&exynos4_spi0_pdata;
>> + break;
>> + case 1:
>> + pd =&exynos4_spi1_pdata;
>> + break;
>> + case 2:
>> + pd =&exynos4_spi2_pdata;
>> + break;
>> + default:
>> + printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
>> + __func__, cntrlr);
>> + return;
>> + }
>> +
>> + pd->num_cs = num_cs;
>> + pd->src_clk_nr = src_clk_nr;
>> +}
>
> I think you can consolidate dev-spi.c in mach-s3c64xx directory. How about
> to move them into plat-samsung/devs.c?
>
> Please refer to next/topic-plat-samsung-devs branch in my tree.
>
>> diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-
>> exynos4/include/mach/irqs.h
>> index 62093b9..a9f0341 100644
>> --- a/arch/arm/mach-exynos4/include/mach/irqs.h
>> +++ b/arch/arm/mach-exynos4/include/mach/irqs.h
>> @@ -70,6 +70,9 @@
>> #define IRQ_IIC5 IRQ_SPI(63)
>> #define IRQ_IIC6 IRQ_SPI(64)
>> #define IRQ_IIC7 IRQ_SPI(65)
>> +#define IRQ_SPI0 IRQ_SPI(66)
>> +#define IRQ_SPI1 IRQ_SPI(67)
>> +#define IRQ_SPI2 IRQ_SPI(68)
>>
>> #define IRQ_USB_HOST IRQ_SPI(70)
>> #define IRQ_USB_HSOTG IRQ_SPI(71)
>> diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-
>> exynos4/include/mach/map.h
>> index 1bea7d1..8dd509e 100644
>> --- a/arch/arm/mach-exynos4/include/mach/map.h
>> +++ b/arch/arm/mach-exynos4/include/mach/map.h
>> @@ -88,6 +88,9 @@
>> #define EXYNOS4_PA_SYSMMU_TV 0x12E20000
>> #define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000
>> #define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000
>> +#define EXYNOS4_PA_SPI0 0x13920000
>> +#define EXYNOS4_PA_SPI1 0x13930000
>> +#define EXYNOS4_PA_SPI2 0x13940000
>>
>> #define EXYNOS4_PA_GPIO1 0x11400000
>> #define EXYNOS4_PA_GPIO2 0x11000000
>> diff --git a/arch/arm/mach-exynos4/include/mach/spi-clocks.h
> b/arch/arm/mach-
>> exynos4/include/mach/spi-clocks.h
>> new file mode 100644
>> index 0000000..576efdf
>> --- /dev/null
>> +++ b/arch/arm/mach-exynos4/include/mach/spi-clocks.h
>> @@ -0,0 +1,16 @@
>> +/* linux/arch/arm/mach-exynos4/include/mach/spi-clocks.h
>> + *
>> + * Copyright (C) 2011 Samsung Electronics Co. Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#ifndef __ASM_ARCH_SPI_CLKS_H
>> +#define __ASM_ARCH_SPI_CLKS_H __FILE__
>> +
>> +/* Must source from SCLK_SPI */
>> +#define EXYNOS4_SPI_SRCCLK_SCLK 0
>> +
>> +#endif /* __ASM_ARCH_SPI_CLKS_H */
>> diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-
>> samsung/include/plat/devs.h
>> index ee5014a..7949131 100644
>> --- a/arch/arm/plat-samsung/include/plat/devs.h
>> +++ b/arch/arm/plat-samsung/include/plat/devs.h
>> @@ -84,6 +84,9 @@ extern struct platform_device s5pv210_device_spi0;
>> extern struct platform_device s5pv210_device_spi1;
>> extern struct platform_device s5p64x0_device_spi0;
>> extern struct platform_device s5p64x0_device_spi1;
>> +extern struct platform_device exynos4_device_spi0;
>> +extern struct platform_device exynos4_device_spi1;
>> +extern struct platform_device exynos4_device_spi2;
>>
>> extern struct platform_device s3c_device_hwmon;
>>
>> diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
> b/arch/arm/plat-
>> samsung/include/plat/s3c64xx-spi.h
>> index c3d82a5..1ec1ea3 100644
>> --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
>> +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
>> @@ -69,5 +69,6 @@ extern void s3c64xx_spi_set_info(int cntrlr, int
> src_clk_nr, int
>> num_cs);
>> extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
>> extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
>> extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
>> +extern void exynos4_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
>>
>> #endif /* __S3C64XX_PLAT_SPI_H */
>> --
>> 1.7.4.4
Hi Padmavathi,
As you know, this needs to re-submit/re-work. Could you please do it as
soon as possible with your other SPI clkdev patches?
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* Re: Chrome brings whole system down
From: Chester @ 2011-10-24 15:23 UTC (permalink / raw)
To: linux-btrfs
In-Reply-To: <CAAE6i0gMgM+LcMPskW-Zyp+mcQZ0a=5+5jvyn7JMnWrYa2G17A@mail.gmail.com>
Just yesterday I can reproduce this reliably. There was no way to turn
the system off other than to use the 'ol REISUB sysrq tricks. I
decided to give it a try today, and it works somehow..
^ permalink raw reply
* Re: kdump: crash_kexec()-smp_send_stop() race in panic
From: Américo Wang @ 2011-10-24 15:23 UTC (permalink / raw)
To: Eric W. Biederman
Cc: heiko.carstens, kexec, linux-kernel, schwidefsky, akpm, holzheu,
Vivek Goyal
In-Reply-To: <m1ipneifqv.fsf@fess.ebiederm.org>
On Mon, Oct 24, 2011 at 11:14 PM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
> Michael Holzheu <holzheu@linux.vnet.ibm.com> writes:
>
>> Hello Vivek,
>>
>> In our tests we ran into the following scenario:
>>
>> Two CPUs have called panic at the same time. The first CPU called
>> crash_kexec() and the second CPU called smp_send_stop() in panic()
>> before crash_kexec() finished on the first CPU. So the second CPU
>> stopped the first CPU and therefore kdump failed.
>>
>> 1st CPU:
>> panic()->crash_kexec()->mutex_trylock(&kexec_mutex)-> do kdump
>>
>> 2nd CPU:
>> panic()->crash_kexec()->kexec_mutex already held by 1st CPU
>> ->smp_send_stop()-> stop CPU 1 (stop kdump)
>>
>> How should we fix this problem? One possibility could be to do
>> smp_send_stop() before we call crash_kexec().
>>
>> What do you think?
>
> smp_send_stop is insufficiently reliable to be used before crash_kexec.
>
> My first reaction would be to test oops_in_progress and wait until
> oops_in_progress == 1 before calling smp_send_stop.
>
+1
One of my colleague mentioned the same problem with me inside
RH, given the fact that the race condition window is small, it would
not be easy to reproduce this scenario.
Thanks.
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
^ permalink raw reply
* Re: kdump: crash_kexec()-smp_send_stop() race in panic
From: Américo Wang @ 2011-10-24 15:23 UTC (permalink / raw)
To: Eric W. Biederman
Cc: holzheu, Vivek Goyal, akpm, schwidefsky, heiko.carstens, kexec,
linux-kernel
In-Reply-To: <m1ipneifqv.fsf@fess.ebiederm.org>
On Mon, Oct 24, 2011 at 11:14 PM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
> Michael Holzheu <holzheu@linux.vnet.ibm.com> writes:
>
>> Hello Vivek,
>>
>> In our tests we ran into the following scenario:
>>
>> Two CPUs have called panic at the same time. The first CPU called
>> crash_kexec() and the second CPU called smp_send_stop() in panic()
>> before crash_kexec() finished on the first CPU. So the second CPU
>> stopped the first CPU and therefore kdump failed.
>>
>> 1st CPU:
>> panic()->crash_kexec()->mutex_trylock(&kexec_mutex)-> do kdump
>>
>> 2nd CPU:
>> panic()->crash_kexec()->kexec_mutex already held by 1st CPU
>> ->smp_send_stop()-> stop CPU 1 (stop kdump)
>>
>> How should we fix this problem? One possibility could be to do
>> smp_send_stop() before we call crash_kexec().
>>
>> What do you think?
>
> smp_send_stop is insufficiently reliable to be used before crash_kexec.
>
> My first reaction would be to test oops_in_progress and wait until
> oops_in_progress == 1 before calling smp_send_stop.
>
+1
One of my colleague mentioned the same problem with me inside
RH, given the fact that the race condition window is small, it would
not be easy to reproduce this scenario.
Thanks.
^ permalink raw reply
* Re: [PATCH V2 04/11] libxl, Introduce dm-version xenstore key.
From: Anthony PERARD @ 2011-10-24 15:22 UTC (permalink / raw)
To: Ian Campbell; +Cc: Xen Devel, Stefano Stabellini
In-Reply-To: <1319450320.3385.176.camel@zakaz.uk.xensource.com>
On Mon, Oct 24, 2011 at 10:58, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Thu, 2011-10-20 at 18:59 +0100, Anthony PERARD wrote:
>> The all key is /libxl/$domid/dm-version.
>>
>> The /libxl/$domid dir is created with the domain and should be only accessible
>> by the toolstack domain.
>>
>> This come with libxl__device_model_version_running helper function.
>>
>> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
>> ---
>> tools/libxl/libxl.c | 2 ++
>> tools/libxl/libxl_create.c | 28 ++++++++++++++++++++++++++++
>> tools/libxl/libxl_internal.c | 19 +++++++++++++++++++
>> tools/libxl/libxl_internal.h | 5 +++++
>> 4 files changed, 54 insertions(+), 0 deletions(-)
>>
>> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
>> index 064fbc4..50b97c2 100644
>> --- a/tools/libxl/libxl.c
>> +++ b/tools/libxl/libxl.c
>> @@ -777,6 +777,8 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, int force)
>> if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
>> LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xs_rm failed for %s", dom_path);
>>
>> + xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "/libxl/%d", domid));
>> +
>> libxl__userdata_destroyall(&gc, domid);
>>
>> rc = xc_domain_destroy(ctx->xch, domid);
>> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
>> index 68d0fc3..bed991c 100644
>> --- a/tools/libxl/libxl_create.c
>> +++ b/tools/libxl/libxl_create.c
>> @@ -322,6 +322,9 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info,
>> xs_transaction_t t = 0;
>> xen_domain_handle_t handle;
>>
>> + struct xs_permissions libxlperm[1];
>> + char *libxl_path = NULL;
>> +
>
> The variable declaration block has little sections of perms and *_path
> -- you might as well include those there. libxlperm might be better
> called noperm (assuming that really is it's meaning, xs's permission
> scheme confuses the hell out of me).
OK, I will change that.
>> assert(!libxl_domid_valid_guest(*domid));
>>
>> uuid_string = libxl__uuid2string(gc, info->uuid);
>> @@ -368,6 +371,15 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info,
>> goto out;
>> }
>>
>> + libxl_path = libxl__sprintf(gc, "/libxl/%i", *domid);
>
> This is probably worthy of a little helper, similar to
> libxl__xs_get_dom_path(). (/vm/blah ought to have one too but doesn't).
I will do it.
>> + if (!libxl_path) {
>> + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot allocate create paths");
>> + rc = ERROR_FAIL;
>> + goto out;
>> + }
>> + libxlperm[0].id = 0;
>> + libxlperm[0].perms = XS_PERM_NONE;
>> +
>> roperm[0].id = 0;
>> roperm[0].perms = XS_PERM_NONE;
>> roperm[1].id = *domid;
>> @@ -386,6 +398,10 @@ retry_transaction:
>> xs_mkdir(ctx->xsh, t, vm_path);
>> xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
>>
>> + xs_rm(ctx->xsh, t, libxl_path);
>> + xs_mkdir(ctx->xsh, t, libxl_path);
>> + xs_set_permissions(ctx->xsh, t, libxl_path, libxlperm, ARRAY_SIZE(libxlperm));
>> +
>> xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
>> rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
>> if (rc)
>> @@ -429,6 +445,16 @@ retry_transaction:
>> return rc;
>> }
>>
>> +static int store_libxl_entry(libxl__gc *gc, uint32_t domid,
>> + libxl_device_model_info *dm_info)
>> +{
>> + char *path = NULL;
>> +
>> + path = libxl__sprintf(gc, "/libxl/%i/dm-version", domid);
>> + return libxl__xs_write(gc, XBT_NULL, path, libxl__strdup(gc,
>> + libxl_device_model_version_to_string(dm_info->device_model_version)));
>> +}
>> +
>> static int do_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
>> libxl_console_ready cb, void *priv,
>> uint32_t *domid_out, int restore_fd)
>> @@ -485,6 +511,8 @@ static int do_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
>> goto error_out;
>> }
>>
>> + store_libxl_entry(gc, domid, dm_info);
>> +
>> for (i = 0; i < d_config->num_disks; i++) {
>> ret = libxl_device_disk_add(ctx, domid, &d_config->disks[i]);
>> if (ret) {
>> diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c
>> index 3993d8e..5d0a2d4 100644
>> --- a/tools/libxl/libxl_internal.c
>> +++ b/tools/libxl/libxl_internal.c
>> @@ -319,6 +319,25 @@ int libxl__fd_set_cloexec(int fd)
>> return fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
>> }
>>
>> +libxl_device_model_version libxl__device_model_version_running(libxl__gc *gc,
>> + uint32_t domid)
>> +{
>> + char *path = NULL;
>> + char *dm_version = NULL;
>> + libxl_device_model_version value;
>> +
>> + path = libxl__sprintf(gc, "/libxl/%d/dm-version", domid);
>> + dm_version = libxl__xs_read(gc, XBT_NULL, path);
>> + if (!dm_version) {
>> + return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
>> + }
>> +
>> + if (libxl_device_model_version_from_string(dm_version, &value) < 0) {
>
> I think this should be a fatal error, if you've managed to read
> something from this key and it isn't one of the expect values then
> something bad has happened.
Yes, I will change this to a fatal error.
>> + return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
>> + }
>> + return value;
>> +}
>> +
>> /*
>> * Local variables:
>> * mode: C
>> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
>> index 2e26ac6..5720b31 100644
>> --- a/tools/libxl/libxl_internal.h
>> +++ b/tools/libxl/libxl_internal.h
>> @@ -554,6 +554,11 @@ _hidden void libxl__json_object_free(libxl__gc *gc, libxl__json_object *obj);
>>
>> _hidden libxl__json_object *libxl__json_parse(libxl__gc *gc, const char *s);
>>
>> + /* Based on /local/domain/$domid/dm-version xenstore key
>> + * default is qemu xen traditional */
>> +_hidden libxl_device_model_version
>> +libxl__device_model_version_running(libxl__gc *gc, uint32_t domid);
>> +
>> #endif
>>
>> /*
--
Anthony PERARD
^ permalink raw reply
* [U-Boot] Accessing MC13783 RTC registers
From: Fabio Estevam @ 2011-10-24 15:22 UTC (permalink / raw)
To: u-boot
In-Reply-To: <4EA56CB7.8010302@denx.de>
Hi Stefano,
On Mon, Oct 24, 2011 at 11:48 AM, Stefano Babic <sbabic@denx.de> wrote:
> I did the same on the qong board to check this issue. On the qong board
> it works:
Thanks for testing it. I managed to get it working on MX31PDK too.
Will submit a patch soon.
Thanks,
Fabio Estevam
^ permalink raw reply
* Re: [PATCH V3 0/4]: ARM: SAMSUNG: Add SPI clkdev support
From: Kukjin Kim @ 2011-10-24 15:19 UTC (permalink / raw)
To: Kukjin Kim
Cc: 'Padmavathi Venna', padma.kvr, linux-samsung-soc,
linux-arm-kernel, ben-linux, linux
In-Reply-To: <039c01cc8730$fb130750$f13915f0$%kim@samsung.com>
On 10/10/11 11:42, Kukjin Kim wrote:
> Padmavathi Venna wrote:
>>
>> This patchset modifies the existing clkdev to make SPI driver
>> independent of the clock names send from platform data. This
>> patches enables the SPI driver to request SPI bus clocks
>> using generic connection ID.
>>
>> V1 patch series are:
>> http://www.spinics.net/lists/arm-kernel/msg141671.html
>>
>> Changes since V1:
>> -Add newly introduced CLKDEV_INIT macro for creating clk_lookup
>> structure as suggested by Russell King
>> V2 patches series are:
>> http://www.spinics.net/lists/arm-kernel/msg142733.html
>>
>> Changes since V2:
>> -Reworked the patches as per the following link. Patch series in
>> the following link removed& and , from the macro declaration and
> added
>> in the macro defination.
>> http://www.spinics.net/lists/arm-kernel/msg143663.html
>>
>> Padmavathi Venna (4):
>> ARM: S3C64XX: Add SPI clkdev support
>> ARM: S5PC100: Add SPI clkdev support
>> ARM: S5P64X0: Add SPI clkdev support
>> ARM: S5PV210: Add SPI clkdev support
>>
>> arch/arm/mach-s3c64xx/clock.c | 98 ++++++++++++++++--------
>> arch/arm/mach-s5p64x0/clock-s5p6440.c | 57 +++++++++-----
>> arch/arm/mach-s5p64x0/clock-s5p6450.c | 57 +++++++++-----
>> arch/arm/mach-s5pc100/clock.c | 132 ++++++++++++++++++++--------
>> -----
>> arch/arm/mach-s5pv210/clock.c | 58 ++++++++++-----
>> 5 files changed, 259 insertions(+), 143 deletions(-)
>>
>> --
>> 1.7.4.4
> Looks ok but this needs 'CLKDEV_INIT' patch. Please wait until it can be
> sent to upstream for this patch.
>
Padmavathi,
As I said, this looks ok and can be applied now.
Could you please rework this based on my next-samsung-dt branch which
includes device tree patches so that I can apply this easily for v3.2?
If any problems, please let me know.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH V3 0/4]: ARM: SAMSUNG: Add SPI clkdev support
From: Kukjin Kim @ 2011-10-24 15:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <039c01cc8730$fb130750$f13915f0$%kim@samsung.com>
On 10/10/11 11:42, Kukjin Kim wrote:
> Padmavathi Venna wrote:
>>
>> This patchset modifies the existing clkdev to make SPI driver
>> independent of the clock names send from platform data. This
>> patches enables the SPI driver to request SPI bus clocks
>> using generic connection ID.
>>
>> V1 patch series are:
>> http://www.spinics.net/lists/arm-kernel/msg141671.html
>>
>> Changes since V1:
>> -Add newly introduced CLKDEV_INIT macro for creating clk_lookup
>> structure as suggested by Russell King
>> V2 patches series are:
>> http://www.spinics.net/lists/arm-kernel/msg142733.html
>>
>> Changes since V2:
>> -Reworked the patches as per the following link. Patch series in
>> the following link removed& and , from the macro declaration and
> added
>> in the macro defination.
>> http://www.spinics.net/lists/arm-kernel/msg143663.html
>>
>> Padmavathi Venna (4):
>> ARM: S3C64XX: Add SPI clkdev support
>> ARM: S5PC100: Add SPI clkdev support
>> ARM: S5P64X0: Add SPI clkdev support
>> ARM: S5PV210: Add SPI clkdev support
>>
>> arch/arm/mach-s3c64xx/clock.c | 98 ++++++++++++++++--------
>> arch/arm/mach-s5p64x0/clock-s5p6440.c | 57 +++++++++-----
>> arch/arm/mach-s5p64x0/clock-s5p6450.c | 57 +++++++++-----
>> arch/arm/mach-s5pc100/clock.c | 132 ++++++++++++++++++++--------
>> -----
>> arch/arm/mach-s5pv210/clock.c | 58 ++++++++++-----
>> 5 files changed, 259 insertions(+), 143 deletions(-)
>>
>> --
>> 1.7.4.4
> Looks ok but this needs 'CLKDEV_INIT' patch. Please wait until it can be
> sent to upstream for this patch.
>
Padmavathi,
As I said, this looks ok and can be applied now.
Could you please rework this based on my next-samsung-dt branch which
includes device tree patches so that I can apply this easily for v3.2?
If any problems, please let me know.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH] regulator: Add S5M8767 regulator driver
From: Sangbeom Kim @ 2011-10-21 10:45 UTC (permalink / raw)
To: lrg, broonie; +Cc: linux-kernel, Sangbeom Kim
S5M8767 is a cost-effective PMIC which is designed for mobile applications.
It includes high efficient 8 Buck converters, 27 LDOs, and an RTC.
This patch implement regulator driver for S5M8767.
Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
---
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/s5m8767.c | 852 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 861 insertions(+), 0 deletions(-)
create mode 100644 drivers/regulator/s5m8767.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index c7fd2c0..9d35b8e 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -125,6 +125,14 @@ config REGULATOR_MAX8998
via I2C bus. The provided regulator is suitable for S3C6410
and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
+config REGULATOR_S5M8767
+ tristate "Samsung S5M8767 voltage regulator"
+ depends on MFD_S5M_CORE
+ help
+ This driver controls a Samsung S5M8767 voltage output regulator
+ via I2C bus. S5M8767 have 8 Bucks and 27 LDOs output and
+ supports 8 DVS modes ranging from 0.65V to 2.225V by 6.25mV steps.
+
config REGULATOR_TWL4030
bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
depends on TWL4030_CORE
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 040d5aa..478fc0f 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -45,5 +45,6 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
+obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
new file mode 100644
index 0000000..2c4c10c
--- /dev/null
+++ b/drivers/regulator/s5m8767.c
@@ -0,0 +1,852 @@
+/*
+ * s5m8767.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/s5m87xx/s5m-pmic.h>
+#include <linux/mfd/s5m87xx/s5m-core.h>
+
+struct s5m8767_info {
+ struct device *dev;
+ struct s5m87xx_dev *iodev;
+ int num_regulators;
+ struct regulator_dev **rdev;
+ int ramp_delay;
+ bool buck2_ramp;
+ bool buck3_ramp;
+ bool buck4_ramp;
+
+ bool buck2_gpiodvs;
+ bool buck3_gpiodvs;
+ bool buck4_gpiodvs;
+ u8 buck2_vol[8];
+ u8 buck3_vol[8];
+ u8 buck4_vol[8];
+ int buck_gpios[3];
+ int buck_gpioindex;
+};
+
+struct s5m_voltage_desc {
+ int max;
+ int min;
+ int step;
+};
+
+static const struct s5m_voltage_desc buck_voltage_val = {
+ .max = 2225000,
+ .min = 650000,
+ .step = 6250,
+};
+
+static const struct s5m_voltage_desc ldo_voltage_val = {
+ .max = 3950000,
+ .min = 800000,
+ .step = 50000,
+};
+
+static const struct s5m_voltage_desc *reg_voltage_map[] = {
+ [S5M8767_LDO1] = &ldo_voltage_val,
+ [S5M8767_LDO2] = &ldo_voltage_val,
+ [S5M8767_LDO3] = &ldo_voltage_val,
+ [S5M8767_LDO4] = &ldo_voltage_val,
+ [S5M8767_LDO5] = &ldo_voltage_val,
+ [S5M8767_LDO6] = &ldo_voltage_val,
+ [S5M8767_LDO7] = &ldo_voltage_val,
+ [S5M8767_LDO8] = &ldo_voltage_val,
+ [S5M8767_LDO9] = &ldo_voltage_val,
+ [S5M8767_LDO10] = &ldo_voltage_val,
+ [S5M8767_LDO11] = &ldo_voltage_val,
+ [S5M8767_LDO12] = &ldo_voltage_val,
+ [S5M8767_LDO13] = &ldo_voltage_val,
+ [S5M8767_LDO14] = &ldo_voltage_val,
+ [S5M8767_LDO15] = &ldo_voltage_val,
+ [S5M8767_LDO16] = &ldo_voltage_val,
+ [S5M8767_LDO17] = &ldo_voltage_val,
+ [S5M8767_LDO18] = &ldo_voltage_val,
+ [S5M8767_LDO19] = &ldo_voltage_val,
+ [S5M8767_LDO20] = &ldo_voltage_val,
+ [S5M8767_LDO21] = &ldo_voltage_val,
+ [S5M8767_LDO22] = &ldo_voltage_val,
+ [S5M8767_LDO23] = &ldo_voltage_val,
+ [S5M8767_LDO24] = &ldo_voltage_val,
+ [S5M8767_LDO25] = &ldo_voltage_val,
+ [S5M8767_LDO26] = &ldo_voltage_val,
+ [S5M8767_LDO27] = &ldo_voltage_val,
+ [S5M8767_BUCK1] = &buck_voltage_val,
+ [S5M8767_BUCK2] = &buck_voltage_val,
+ [S5M8767_BUCK3] = &buck_voltage_val,
+ [S5M8767_BUCK4] = &buck_voltage_val,
+ [S5M8767_BUCK5] = &buck_voltage_val,
+ [S5M8767_BUCK6] = &buck_voltage_val,
+ [S5M8767_BUCK7] = NULL,
+ [S5M8767_BUCK8] = NULL,
+};
+
+static inline int s5m8767_get_regid(struct regulator_dev *rdev)
+{
+ return rdev_get_id(rdev);
+}
+
+static inline int s5m8767_is_buck(struct regulator_dev *rdev)
+{
+ int reg_id = s5m8767_get_regid(rdev);
+
+ return reg_id < S5M8767_LDO27;
+}
+
+static int s5m8767_list_voltage(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ const struct s5m_voltage_desc *desc;
+ int reg_id = s5m8767_get_regid(rdev);
+ int val;
+
+ if (reg_id >= ARRAY_SIZE(reg_voltage_map) || reg_id < 0)
+ return -EINVAL;
+
+ desc = reg_voltage_map[reg_id];
+ if (desc == NULL)
+ return -EINVAL;
+
+ val = desc->min + desc->step * selector;
+ if (val > desc->max)
+ return -EINVAL;
+
+ return val;
+}
+
+static int s5m8767_get_register(struct regulator_dev *rdev, int *reg)
+{
+ int reg_id = s5m8767_get_regid(rdev);
+
+ switch (reg_id) {
+ case S5M8767_LDO1 ... S5M8767_LDO27:
+ *reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);
+ break;
+ case S5M8767_BUCK1:
+ *reg = S5M8767_REG_BUCK1CTRL1;
+ break;
+ case S5M8767_BUCK2 ... S5M8767_BUCK4:
+ *reg = S5M8767_REG_BUCK2CTRL + (reg_id - S5M8767_BUCK2) * 9;
+ break;
+ case S5M8767_BUCK5 ... S5M8767_BUCK8:
+ *reg = S5M8767_REG_BUCK5CTRL1 + (reg_id - S5M8767_BUCK5) * 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int s5m8767_reg_is_enabled(struct regulator_dev *rdev)
+{
+ struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
+ int ret, reg;
+ int mask=0x01, pattern=0x01;
+ u8 val;
+ int reg_id = s5m8767_get_regid(rdev);
+
+ switch (reg_id) {
+ case S5M8767_LDO1 ... S5M8767_LDO27:
+ mask = 0xc0;
+ pattern = 0xc0;
+ break;
+ case S5M8767_BUCK1 ... S5M8767_BUCK8:
+ break;
+ }
+
+ ret = s5m8767_get_register(rdev, ®);
+ if (ret == -EINVAL)
+ return 1;
+ else if (ret)
+ return ret;
+
+ ret = s5m_reg_read(s5m8767->iodev, reg, &val);
+ if (ret)
+ return ret;
+
+ return (val & mask) == pattern;
+}
+
+static int s5m8767_reg_enable(struct regulator_dev *rdev)
+{
+ struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
+ int ret, reg;
+ int mask=0, pattern=0;
+ int reg_id = s5m8767_get_regid(rdev);
+
+ switch (reg_id) {
+ case S5M8767_LDO1 ... S5M8767_LDO27:
+ mask = 0xc0;
+ pattern = 0xc0;
+ break;
+ case S5M8767_BUCK1 ... S5M8767_BUCK8:
+ mask = 0x01;
+ pattern = 0x01;
+ break;
+ }
+
+ ret = s5m8767_get_register(rdev, ®);
+ if (ret)
+ return ret;
+
+ return s5m_reg_update(s5m8767->iodev, reg, pattern, mask);
+}
+
+static int s5m8767_reg_disable(struct regulator_dev *rdev)
+{
+ struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
+ int ret, reg;
+ int mask=0, pattern=0;
+ int reg_id = s5m8767_get_regid(rdev);
+
+ switch (reg_id) {
+ case S5M8767_LDO1 ... S5M8767_LDO27:
+ mask = 0xc0;
+ pattern = 0xc0;
+ break;
+ case S5M8767_BUCK1 ... S5M8767_BUCK8:
+ mask = 0x01;
+ pattern = 0x01;
+ break;
+ }
+
+ ret = s5m8767_get_register(rdev, ®);
+ if (ret)
+ return ret;
+
+ return s5m_reg_update(s5m8767->iodev, reg, ~pattern, mask);
+}
+
+static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
+{
+ int reg_id = s5m8767_get_regid(rdev);
+ int reg;
+
+ switch (reg_id) {
+ case S5M8767_LDO1 ... S5M8767_LDO27:
+ reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);
+ break;
+ case S5M8767_BUCK1:
+ reg = S5M8767_REG_BUCK1CTRL2;
+ break;
+ case S5M8767_BUCK2:
+ reg = S5M8767_REG_BUCK2DVS1;
+ break;
+ case S5M8767_BUCK3:
+ reg = S5M8767_REG_BUCK3DVS1;
+ break;
+ case S5M8767_BUCK4:
+ reg = S5M8767_REG_BUCK4DVS1;
+ break;
+ case S5M8767_BUCK5 ... S5M8767_BUCK8:
+ reg = S5M8767_REG_BUCK5CTRL2 + (reg_id - S5M8767_BUCK5) * 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *_reg = reg;
+
+ return 0;
+}
+
+static int s5m8767_get_voltage(struct regulator_dev *rdev)
+{
+ struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
+ int reg, mask=0xff, ret;
+ int reg_id = s5m8767_get_regid(rdev);
+ u8 val;
+
+ ret = s5m8767_get_voltage_register(rdev, ®);
+ if (ret)
+ return ret;
+
+ switch (reg_id) {
+ case S5M8767_LDO1 ... S5M8767_LDO27:
+ mask = 0x3f;
+ break;
+ case S5M8767_BUCK2:
+ if(s5m8767->buck2_gpiodvs)
+ reg += s5m8767->buck_gpioindex;
+ break;
+ case S5M8767_BUCK3:
+ if(s5m8767->buck3_gpiodvs)
+ reg += s5m8767->buck_gpioindex;
+ break;
+ case S5M8767_BUCK4:
+ if(s5m8767->buck4_gpiodvs)
+ reg += s5m8767->buck_gpioindex;
+ break;
+ }
+
+ ret = s5m_reg_read(s5m8767->iodev, reg, &val);
+ if (ret)
+ return ret;
+
+ val &= mask;
+
+ if (rdev->desc && rdev->desc->ops && rdev->desc->ops->list_voltage)
+ return rdev->desc->ops->list_voltage(rdev, val);
+
+ return s5m8767_list_voltage(rdev, val);
+}
+
+static inline int s5m8767_convert_voltage(
+ const struct s5m_voltage_desc *desc,
+ int min_vol, int max_vol)
+{
+ int i = 0;
+
+ if (desc == NULL)
+ return -EINVAL;
+
+ if (max_vol < desc->min || min_vol > desc->max)
+ return -EINVAL;
+
+ i = (min_vol - desc->min) / desc->step;
+
+ if (desc->min + desc->step * i > max_vol)
+ return -EINVAL;
+
+ return i;
+}
+
+static int s5m8767_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV, unsigned *selector)
+{
+ struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
+ int min_vol = min_uV, max_vol = max_uV;
+ const struct s5m_voltage_desc *desc;
+ int reg_id = s5m8767_get_regid(rdev);
+ int reg, mask, ret;
+ int i;
+ u8 val;
+
+ switch (reg_id) {
+ case S5M8767_LDO1 ... S5M8767_LDO27:
+ mask = 0x3f;
+ break;
+ case S5M8767_BUCK1 ... S5M8767_BUCK6:
+ mask = 0xff;
+ break;
+ case S5M8767_BUCK7 ... S5M8767_BUCK8:
+ return -EINVAL;
+ default:
+ return -EINVAL;
+ }
+
+ desc = reg_voltage_map[reg_id];
+
+ i = s5m8767_convert_voltage(desc, min_vol, max_vol);
+ if (i < 0)
+ return i;
+
+ ret = s5m8767_get_voltage_register(rdev, ®);
+ if (ret)
+ return ret;
+
+ s5m_reg_read(s5m8767->iodev, reg, &val);
+ val = val & mask;
+
+ ret = s5m_reg_update(s5m8767->iodev, reg, i, mask);
+ *selector = i;
+
+ if (val < i)
+ udelay(DIV_ROUND_UP(desc->step * (i - val),
+ s5m8767->ramp_delay));
+
+ return ret;
+}
+
+static inline void s5m8767_set_high(struct s5m8767_info *s5m8767)
+{
+ int temp_index = s5m8767->buck_gpioindex;
+
+ gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
+ gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
+ gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
+}
+
+static inline void s5m8767_set_low(struct s5m8767_info *s5m8767)
+{
+ int temp_index = s5m8767->buck_gpioindex;
+
+ gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
+ gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
+ gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
+}
+
+static int s5m8767_set_voltage_buck(struct regulator_dev *rdev,
+ int min_uV, int max_uV, unsigned *selector)
+{
+ struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
+ int reg_id = s5m8767_get_regid(rdev);
+ const struct s5m_voltage_desc *desc;
+ int new_val, old_val, i = 0;
+ int min_vol = min_uV, max_vol = max_uV;
+
+ if (reg_id < S5M8767_BUCK1 || reg_id > S5M8767_BUCK6)
+ return -EINVAL;
+
+ switch (reg_id) {
+ case S5M8767_BUCK1:
+ return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
+ case S5M8767_BUCK2 ... S5M8767_BUCK4:
+ break;
+ case S5M8767_BUCK5 ... S5M8767_BUCK6:
+ return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
+ }
+
+ desc = reg_voltage_map[reg_id];
+ new_val = s5m8767_convert_voltage(desc, min_vol, max_vol);
+ if (new_val < 0)
+ return new_val;
+
+ switch (reg_id) {
+ case S5M8767_BUCK2:
+ if(s5m8767->buck2_gpiodvs){
+ while (s5m8767->buck2_vol[i] != new_val)
+ i++;
+ }
+ else
+ return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
+ break;
+ case S5M8767_BUCK3:
+ if(s5m8767->buck3_gpiodvs){
+ while (s5m8767->buck3_vol[i] != new_val)
+ i++;
+ } else
+ return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
+ break;
+ case S5M8767_BUCK4:
+ if(s5m8767->buck3_gpiodvs){
+ while (s5m8767->buck4_vol[i] != new_val)
+ i++;
+ } else
+ return s5m8767_set_voltage(rdev, min_uV, max_uV, selector);
+ break;
+ }
+
+ old_val = s5m8767->buck_gpioindex;
+ s5m8767->buck_gpioindex = i;
+
+ if ( i > old_val)
+ s5m8767_set_high(s5m8767);
+ else
+ s5m8767_set_low(s5m8767);
+
+ *selector = new_val;
+ return 0;
+}
+
+static int s5m8767_reg_enable_suspend(struct regulator_dev *rdev)
+{
+ return 0;
+}
+
+static int s5m8767_reg_disable_suspend(struct regulator_dev *rdev)
+{
+ struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
+ int ret, reg;
+ int mask=0, pattern=0;
+ int reg_id = s5m8767_get_regid(rdev);
+
+ switch (reg_id) {
+ case S5M8767_LDO1 ... S5M8767_LDO27:
+ mask = 0xc0;
+ pattern = 0xc0;
+ break;
+ case S5M8767_BUCK1 ... S5M8767_BUCK8:
+ mask = 0x01;
+ pattern = 0x01;
+ break;
+ }
+
+ ret = s5m8767_get_register(rdev, ®);
+ if (ret)
+ return ret;
+
+ return s5m_reg_update(s5m8767->iodev, reg, ~pattern, mask);
+}
+
+static struct regulator_ops s5m8767_ldo_ops = {
+ .list_voltage = s5m8767_list_voltage,
+ .is_enabled = s5m8767_reg_is_enabled,
+ .enable = s5m8767_reg_enable,
+ .disable = s5m8767_reg_disable,
+ .get_voltage = s5m8767_get_voltage,
+ .set_voltage = s5m8767_set_voltage,
+ .set_suspend_enable = s5m8767_reg_enable_suspend,
+ .set_suspend_disable = s5m8767_reg_disable_suspend,
+};
+
+static struct regulator_ops s5m8767_buck_ops = {
+ .list_voltage = s5m8767_list_voltage,
+ .is_enabled = s5m8767_reg_is_enabled,
+ .enable = s5m8767_reg_enable,
+ .disable = s5m8767_reg_disable,
+ .get_voltage = s5m8767_get_voltage,
+ .set_voltage = s5m8767_set_voltage_buck,
+ .set_suspend_enable = s5m8767_reg_enable_suspend,
+ .set_suspend_disable = s5m8767_reg_disable_suspend,
+};
+
+static struct regulator_ops s5m8767_others_ops = {
+ .is_enabled = s5m8767_reg_is_enabled,
+ .enable = s5m8767_reg_enable,
+ .disable = s5m8767_reg_disable,
+ .set_suspend_enable = s5m8767_reg_enable_suspend,
+ .set_suspend_disable = s5m8767_reg_disable_suspend,
+};
+
+#define regulator_desc_ldo(num) { \
+ .name = "LDO"#num, \
+ .id = S5M8767_LDO##num, \
+ .ops = &s5m8767_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+}
+#define regulator_desc_buck(num) { \
+ .name = "BUCK"#num, \
+ .id = S5M8767_BUCK##num, \
+ .ops = &s5m8767_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+}
+
+static struct regulator_desc regulators[] = {
+ regulator_desc_ldo(1),
+ regulator_desc_ldo(2),
+ regulator_desc_ldo(3),
+ regulator_desc_ldo(4),
+ regulator_desc_ldo(5),
+ regulator_desc_ldo(6),
+ regulator_desc_ldo(7),
+ regulator_desc_ldo(8),
+ regulator_desc_ldo(9),
+ regulator_desc_ldo(10),
+ regulator_desc_ldo(11),
+ regulator_desc_ldo(12),
+ regulator_desc_ldo(13),
+ regulator_desc_ldo(14),
+ regulator_desc_ldo(15),
+ regulator_desc_ldo(16),
+ regulator_desc_ldo(17),
+ regulator_desc_ldo(18),
+ regulator_desc_ldo(19),
+ regulator_desc_ldo(20),
+ regulator_desc_ldo(21),
+ regulator_desc_ldo(22),
+ regulator_desc_ldo(23),
+ regulator_desc_ldo(24),
+ regulator_desc_ldo(25),
+ regulator_desc_ldo(26),
+ regulator_desc_ldo(27),
+ regulator_desc_buck(1),
+ regulator_desc_buck(2),
+ regulator_desc_buck(3),
+ regulator_desc_buck(4),
+ regulator_desc_buck(5),
+ regulator_desc_buck(6),
+ regulator_desc_buck(7),
+ regulator_desc_buck(8),
+ {
+ .name = "AP 32KHz",
+ .id = S5M8767_32KHZAP_EN,
+ .ops = &s5m8767_others_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ }, {
+ .name = "CP 32KHz",
+ .id = S5M8767_32KHZAP_EN,
+ .ops = &s5m8767_others_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+};
+
+static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
+{
+ struct s5m87xx_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct s5m87xx_platform_data *pdata = dev_get_platdata(iodev->dev);
+ struct regulator_dev **rdev;
+ struct s5m8767_info *s5m8767;
+ struct i2c_client *i2c;
+ int i, ret, size, reg;
+ u8 val;
+
+ if (!pdata) {
+ dev_err(pdev->dev.parent, "Platform data not supplied\n");
+ return -ENODEV;
+ }
+
+ s5m8767 = kzalloc(sizeof(struct s5m8767_info), GFP_KERNEL);
+ if (!s5m8767)
+ return -ENOMEM;
+
+ size = sizeof(struct regulator_dev *) * pdata->num_regulators;
+ s5m8767->rdev = kzalloc(size, GFP_KERNEL);
+ if (!s5m8767->rdev) {
+ kfree(s5m8767);
+ return -ENOMEM;
+ }
+
+ rdev = s5m8767->rdev;
+ s5m8767->dev = &pdev->dev;
+ s5m8767->iodev = iodev;
+ s5m8767->num_regulators = pdata->num_regulators;
+ platform_set_drvdata(pdev, s5m8767);
+ i2c = s5m8767->iodev->i2c;
+
+ s5m8767->buck_gpioindex = pdata->buck_default_idx;
+ s5m8767->buck2_gpiodvs = pdata->buck2_gpiodvs;
+ s5m8767->buck3_gpiodvs = pdata->buck3_gpiodvs;
+ s5m8767->buck4_gpiodvs = pdata->buck4_gpiodvs;
+ s5m8767->buck_gpios[0] = pdata->buck_gpios[0];
+ s5m8767->buck_gpios[1] = pdata->buck_gpios[1];
+ s5m8767->buck_gpios[2] = pdata->buck_gpios[2];
+ s5m8767->ramp_delay = pdata->buck_ramp_delay;
+ s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
+ s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
+ s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
+
+ for (i = 0; i < 8; i++) {
+ if (s5m8767->buck2_gpiodvs) {
+ s5m8767->buck2_vol[i] =
+ s5m8767_convert_voltage(
+ &buck_voltage_val,
+ pdata->buck2_voltage[i],
+ pdata->buck2_voltage[i] +
+ buck_voltage_val.step);
+ }
+
+ if (s5m8767->buck3_gpiodvs) {
+ s5m8767->buck3_vol[i] =
+ s5m8767_convert_voltage(
+ &buck_voltage_val,
+ pdata->buck3_voltage[i],
+ pdata->buck3_voltage[i] +
+ buck_voltage_val.step);
+ }
+
+ if (s5m8767->buck4_gpiodvs) {
+ s5m8767->buck4_vol[i] =
+ s5m8767_convert_voltage(
+ &buck_voltage_val,
+ pdata->buck4_voltage[i],
+ pdata->buck4_voltage[i] +
+ buck_voltage_val.step);
+ }
+
+ }
+
+ if(pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
+ pdata->buck4_gpiodvs) {
+ if (gpio_is_valid(pdata->buck_gpios[0]) &&
+ gpio_is_valid(pdata->buck_gpios[1]) &&
+ gpio_is_valid(pdata->buck_gpios[2])) {
+ ret = gpio_request(pdata->buck_gpios[0],
+ "S5M8767 SET1");
+ if (ret == -EBUSY)
+ dev_warn(&pdev->dev, "Duplicated gpio request"
+ " for SET1\n");
+
+ ret = gpio_request(pdata->buck_gpios[1],
+ "S5M8767 SET2");
+ if (ret == -EBUSY)
+ dev_warn(&pdev->dev, "Duplicated gpio request"
+ " for SET2\n");
+
+ ret = gpio_request(pdata->buck_gpios[2],
+ "S5M8767 SET3");
+ if (ret == -EBUSY)
+ dev_warn(&pdev->dev, "Duplicated gpio request"
+ " for SET3\n");
+ /* SET1 GPIO */
+ gpio_direction_output(pdata->buck_gpios[0],
+ (s5m8767->buck_gpioindex >> 2) & 0x1);
+ /* SET2 GPIO */
+ gpio_direction_output(pdata->buck_gpios[1],
+ (s5m8767->buck_gpioindex >> 1) & 0x1);
+ /* SET3 GPIO */
+ gpio_direction_output(pdata->buck_gpios[2],
+ (s5m8767->buck_gpioindex >> 0) & 0x1);
+ ret = 0;
+ } else {
+ dev_err(&pdev->dev, "GPIO ISN'T VALID\n");
+ ret = -EINVAL;
+ goto err_alloc;
+ }
+ }
+
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, (pdata->buck2_gpiodvs) ?
+ (1 << 1) : (0 << 1), 1 << 1);
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, (pdata->buck3_gpiodvs) ?
+ (1 << 1) : (0 << 1), 1 << 1);
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, (pdata->buck4_gpiodvs) ?
+ (1 << 1) : (0 << 1), 1 << 1);
+
+ /* Initialize GPIO DVS registers */
+ for (i = 0; i < 8; i++) {
+ if (s5m8767->buck2_gpiodvs) {
+ s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS1 + i,
+ s5m8767->buck2_vol[i]);
+ }
+
+ if (s5m8767->buck3_gpiodvs) {
+ s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS1 + i,
+ s5m8767->buck3_vol[i]);
+ }
+
+ if (s5m8767->buck4_gpiodvs) {
+ s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS1 + i,
+ s5m8767->buck4_vol[i]);
+ }
+ }
+
+ reg = S5M8767_REG_LDO7CTRL;
+
+ do{
+ ret = s5m_reg_read(s5m8767->iodev, reg, &val);
+ if (ret)
+ return ret;
+
+ s5m_reg_update(s5m8767->iodev, reg, ((val & 0x3f) | 0x80), 0xff);
+ reg++;
+ if ((reg == S5M8767_REG_LDO9CTRL)
+ || (reg == S5M8767_REG_LDO11CTRL)
+ || (reg == S5M8767_REG_LDO13CTRL)
+ || (reg == S5M8767_REG_LDO17CTRL))
+ reg++;
+ } while (reg <= S5M8767_REG_LDO27CTRL);
+
+ if (s5m8767->buck2_ramp)
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08);
+
+ if (s5m8767->buck3_ramp)
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x04, 0x04);
+
+ if (s5m8767->buck4_ramp)
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x02, 0x02);
+
+ if (s5m8767->buck2_ramp || s5m8767->buck3_ramp
+ || s5m8767->buck4_ramp) {
+ if (s5m8767->ramp_delay < 15)
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
+ s5m8767->ramp_delay - 1, 0xf0);
+ else if (s5m8767->ramp_delay == 15)
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
+ 0xc0, 0xf0);
+ else if (s5m8767->ramp_delay == 25)
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
+ 0xd0, 0xf0);
+ else if (s5m8767->ramp_delay == 50)
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
+ 0xe0, 0xf0);
+ else if (s5m8767->ramp_delay == 100)
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
+ 0xf0, 0xf0);
+ else
+ s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
+ 0x90, 0xf0);
+ }
+
+ for (i = 0; i < pdata->num_regulators; i++) {
+ const struct s5m_voltage_desc *desc;
+ int id = pdata->regulators[i].id;
+
+ desc = reg_voltage_map[id];
+ if (desc)
+ regulators[id].n_voltages =
+ (desc->max - desc->min) / desc->step + 1;
+
+ rdev[i] = regulator_register(®ulators[id], s5m8767->dev,
+ pdata->regulators[i].initdata,
+ s5m8767);
+ if (IS_ERR(rdev[i])) {
+ ret = PTR_ERR(rdev[i]);
+ dev_err(s5m8767->dev, "regulator init failed for %d\n",
+ id);
+ rdev[i] = NULL;
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ for (i = 0; i < s5m8767->num_regulators; i++)
+ if (rdev[i])
+ regulator_unregister(rdev[i]);
+err_alloc:
+ kfree(s5m8767->rdev);
+ kfree(s5m8767);
+
+ return ret;
+}
+
+static int __devexit s5m8767_pmic_remove(struct platform_device *pdev)
+{
+ struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
+ struct regulator_dev **rdev = s5m8767->rdev;
+ int i;
+
+ for (i = 0; i < s5m8767->num_regulators; i++)
+ if (rdev[i])
+ regulator_unregister(rdev[i]);
+
+ kfree(s5m8767->rdev);
+ kfree(s5m8767);
+
+ return 0;
+}
+
+static const struct platform_device_id s5m8767_pmic_id[] = {
+ { "s5m8767-pmic", 0},
+ { },
+};
+MODULE_DEVICE_TABLE(platform, s5m8767_pmic_id);
+
+static struct platform_driver s5m8767_pmic_driver = {
+ .driver = {
+ .name = "s5m8767-pmic",
+ .owner = THIS_MODULE,
+ },
+ .probe = s5m8767_pmic_probe,
+ .remove = __devexit_p(s5m8767_pmic_remove),
+ .id_table = s5m8767_pmic_id,
+};
+
+static int __init s5m8767_pmic_init(void)
+{
+ return platform_driver_register(&s5m8767_pmic_driver);
+}
+subsys_initcall(s5m8767_pmic_init);
+
+static void __exit s5m8767_pmic_exit(void)
+{
+ platform_driver_unregister(&s5m8767_pmic_driver);
+}
+module_exit(s5m8767_pmic_exit);
+
+/* Module information */
+MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
+MODULE_DESCRIPTION("SAMSUNG S5M8767 Regulator Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s5m8767-pmic");
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] sparse, llvm: Fix 'void *' pointer code generation
From: Pekka Enberg @ 2011-10-24 15:18 UTC (permalink / raw)
To: Jeff Garzik
Cc: Jonathan Neuschäfer, Linus Torvalds, linux-sparse,
Christopher Li, Jeff Garzik
In-Reply-To: <4EA580B6.4070008@garzik.org>
On Mon, Oct 24, 2011 at 6:13 PM, Jeff Garzik <jeff@garzik.org> wrote:
>> Thanks for pointing that out. Jeff, does this look OK?
>
> I don't know what bit_size==-1 means off the top of my head, so I assume yes
So
void *p;
looks as follows with test-inspect:
0: SYM_NODE: p
ctype.base_type: SYM_PTR: <noident>
ctype.base_type: SYM_BASETYPE: void
[ btw, is there a text mode version of test-inspect? ]
where the SYM_BASETYPE of 'void' has -1 set as bit_size by the frontend.
Pekka
^ permalink raw reply
* [PATCH 1/3] mfd: Add S5M core driver
From: Sangbeom Kim @ 2011-10-21 10:28 UTC (permalink / raw)
To: sameo; +Cc: linux-kernel, broonie, Sangbeom Kim
In-Reply-To: <1319192894-19292-1-git-send-email-sbkim73@samsung.com>
S5M series are pmic including mutiple functions.
It can support PMIC, RTC, Battery charger, codec.
This patch implement core driver for s5m series.
Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
---
drivers/mfd/s5m-core.c | 235 +++++++++++++++++++++++++
include/linux/mfd/s5m87xx/s5m-core.h | 313 ++++++++++++++++++++++++++++++++++
include/linux/mfd/s5m87xx/s5m-pmic.h | 141 +++++++++++++++
include/linux/mfd/s5m87xx/s5m-rtc.h | 69 ++++++++
4 files changed, 758 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/s5m-core.c
create mode 100644 include/linux/mfd/s5m87xx/s5m-core.h
create mode 100644 include/linux/mfd/s5m87xx/s5m-pmic.h
create mode 100644 include/linux/mfd/s5m87xx/s5m-rtc.h
diff --git a/drivers/mfd/s5m-core.c b/drivers/mfd/s5m-core.c
new file mode 100644
index 0000000..6dac3a1
--- /dev/null
+++ b/drivers/mfd/s5m-core.c
@@ -0,0 +1,235 @@
+/*
+ * s5m-core.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/mutex.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/s5m87xx/s5m-core.h>
+#include <linux/mfd/s5m87xx/s5m-pmic.h>
+#include <linux/mfd/s5m87xx/s5m-rtc.h>
+#include <linux/regmap.h>
+
+int s5m_reg_read(struct s5m87xx_dev *s5m87xx, u8 reg, u8 *dest)
+{
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(s5m87xx->regmap, reg, &val);
+
+ if (ret < 0)
+ return ret;
+
+ ret &= 0xff;
+ *dest = ret;
+ return 0;
+}
+EXPORT_SYMBOL(s5m_reg_read);
+
+int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
+{
+ int ret;
+
+ ret = regmap_bulk_read(s5m87xx->regmap, reg, buf, count);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(s5m_bulk_read);
+
+int s5m_reg_write(struct s5m87xx_dev *s5m87xx, u8 reg, u8 value)
+{
+ int ret;
+
+ ret = regmap_write(s5m87xx->regmap, reg, value);
+ return ret;
+}
+EXPORT_SYMBOL(s5m_reg_write);
+
+int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
+{
+ int ret;
+
+ ret = regmap_raw_write(s5m87xx->regmap, reg, buf, count * sizeof(u16));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(s5m_bulk_write);
+
+int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask)
+{
+ int ret;
+
+ ret = regmap_update_bits(s5m87xx->regmap, reg, mask, val);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+EXPORT_SYMBOL(s5m_reg_update);
+
+static struct mfd_cell s5m87xx_devs[] = {
+ {
+ .name = "s5m8763-pmic",
+ }, {
+ .name = "s5m8767-pmic",
+ }, {
+ .name = "s5m-rtc",
+ }, {
+ .name = "s5m8763-charger",
+ },
+};
+
+static struct regmap_config s5m_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int s5m_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct s5m87xx_platform_data *pdata = i2c->dev.platform_data;
+ struct s5m87xx_dev *s5m87xx;
+ int ret = 0;
+ int error;
+
+ s5m87xx = kzalloc(sizeof(struct s5m87xx_dev), GFP_KERNEL);
+ if (s5m87xx == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, s5m87xx);
+ s5m87xx->dev = &i2c->dev;
+ s5m87xx->i2c = i2c;
+ s5m87xx->irq = i2c->irq;
+ s5m87xx->type = id->driver_data;
+
+ if (pdata) {
+ s5m87xx->device_type = pdata->device_type;
+ s5m87xx->ono = pdata->ono;
+ s5m87xx->irq_base = pdata->irq_base;
+ s5m87xx->wakeup = pdata->wakeup;
+ }
+
+ s5m87xx->regmap = regmap_init_i2c(i2c, &s5m_regmap_config);
+ if (IS_ERR(s5m87xx->regmap)) {
+ error = PTR_ERR(s5m87xx->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ error);
+ goto err;
+ }
+
+ s5m87xx->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
+ i2c_set_clientdata(s5m87xx->rtc, s5m87xx);
+
+ s5m_irq_init(s5m87xx);
+
+ pm_runtime_set_active(s5m87xx->dev);
+
+ ret = mfd_add_devices(s5m87xx->dev, -1,
+ s5m87xx_devs, ARRAY_SIZE(s5m87xx_devs),
+ NULL, 0);
+ if (ret < 0)
+ goto err;
+
+ dev_info(s5m87xx->dev ,"SAMSUNG S5M MFD\n");
+ return ret;
+
+err:
+ mfd_remove_devices(s5m87xx->dev);
+ s5m_irq_exit(s5m87xx);
+ i2c_unregister_device(s5m87xx->rtc);
+ regmap_exit(s5m87xx->regmap);
+ kfree(s5m87xx);
+ return ret;
+}
+
+static int s5m_i2c_remove(struct i2c_client *i2c)
+{
+ struct s5m87xx_dev *s5m87xx = i2c_get_clientdata(i2c);
+
+ mfd_remove_devices(s5m87xx->dev);
+ s5m_irq_exit(s5m87xx);
+ i2c_unregister_device(s5m87xx->rtc);
+ regmap_exit(s5m87xx->regmap);
+ kfree(s5m87xx);
+
+ return 0;
+}
+
+static const struct i2c_device_id s5m87xx_i2c_id[] = {
+ { "s5m87xx", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, s5m87xx_i2c_id);
+
+static int s5m_suspend(struct i2c_client *i2c, pm_message_t state)
+{
+ struct s5m87xx_dev *s5m87xx = i2c_get_clientdata(i2c);
+
+ if (s5m87xx->wakeup)
+ enable_irq_wake(s5m87xx->irq);
+
+ disable_irq(s5m87xx->irq);
+
+ return 0;
+}
+
+static int s5m_resume(struct i2c_client *i2c)
+{
+ struct s5m87xx_dev *s5m87xx = i2c_get_clientdata(i2c);
+
+ if (s5m87xx->wakeup)
+ disable_irq_wake(s5m87xx->irq);
+
+ enable_irq(s5m87xx->irq);
+
+ return 0;
+}
+
+static struct i2c_driver s5m87xx_i2c_driver = {
+ .driver = {
+ .name = "s5m87xx",
+ .owner = THIS_MODULE,
+ },
+ .probe = s5m_i2c_probe,
+ .remove = s5m_i2c_remove,
+ .id_table = s5m87xx_i2c_id,
+ .suspend = s5m_suspend,
+ .resume = s5m_resume,
+};
+
+static int __init s5m87xx_i2c_init(void)
+{
+ return i2c_add_driver(&s5m87xx_i2c_driver);
+}
+
+subsys_initcall(s5m87xx_i2c_init);
+
+static void __exit s5m87xx_i2c_exit(void)
+{
+ i2c_del_driver(&s5m87xx_i2c_driver);
+}
+module_exit(s5m87xx_i2c_exit);
+
+MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
+MODULE_DESCRIPTION("Core support for the S5M87XX MFD");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/s5m87xx/s5m-core.h b/include/linux/mfd/s5m87xx/s5m-core.h
new file mode 100644
index 0000000..ddacd5b
--- /dev/null
+++ b/include/linux/mfd/s5m87xx/s5m-core.h
@@ -0,0 +1,313 @@
+/*
+ * s5m-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_S5M_CORE_H
+#define __LINUX_MFD_S5M_CORE_H
+
+#define NUM_IRQ_REGS 4
+
+enum s5m_device_type {
+ S5M8751X,
+ S5M8763X,
+ S5M8767X,
+};
+
+/* S5M8767 registers */
+enum s5m8767_reg {
+ S5M8767_REG_ID,
+ S5M8767_REG_INT1,
+ S5M8767_REG_INT2,
+ S5M8767_REG_INT3,
+ S5M8767_REG_INT1M,
+ S5M8767_REG_INT2M,
+ S5M8767_REG_INT3M,
+ S5M8767_REG_STATUS1,
+ S5M8767_REG_STATUS2,
+ S5M8767_REG_STATUS3,
+ S5M8767_REG_CTRL1,
+ S5M8767_REG_CTRL2,
+ S5M8767_REG_LOWBAT1,
+ S5M8767_REG_LOWBAT2,
+ S5M8767_REG_BUCHG,
+ S5M8767_REG_DVSRAMP,
+ S5M8767_REG_DVSTIMER1,
+ S5M8767_REG_DVSTIMER2,
+ S5M8767_REG_DVSTIMER3,
+ S5M8767_REG_DVSTIMER4,
+ S5M8767_REG_LDO1,
+ S5M8767_REG_LDO2,
+ S5M8767_REG_LDO3,
+ S5M8767_REG_LDO4,
+ S5M8767_REG_LDO5,
+ S5M8767_REG_LDO6,
+ S5M8767_REG_LDO7,
+ S5M8767_REG_LDO8,
+ S5M8767_REG_LDO9,
+ S5M8767_REG_LDO10,
+ S5M8767_REG_LDO11,
+ S5M8767_REG_LDO12,
+ S5M8767_REG_LDO13,
+ S5M8767_REG_LDO14,
+ S5M8767_REG_LDO15,
+ S5M8767_REG_LDO16,
+ S5M8767_REG_LDO17,
+ S5M8767_REG_LDO18,
+ S5M8767_REG_LDO19,
+ S5M8767_REG_LDO20,
+ S5M8767_REG_LDO21,
+ S5M8767_REG_LDO22,
+ S5M8767_REG_LDO23,
+ S5M8767_REG_LDO24,
+ S5M8767_REG_LDO25,
+ S5M8767_REG_LDO26,
+ S5M8767_REG_LDO27,
+ S5M8767_REG_BUCK1CTRL1 = 0x35,
+ S5M8767_REG_BUCK1CTRL2,
+ S5M8767_REG_BUCK2CTRL,
+ S5M8767_REG_BUCK2DVS1,
+ S5M8767_REG_BUCK2DVS2,
+ S5M8767_REG_BUCK2DVS3,
+ S5M8767_REG_BUCK2DVS4,
+ S5M8767_REG_BUCK2DVS5,
+ S5M8767_REG_BUCK2DVS6,
+ S5M8767_REG_BUCK2DVS7,
+ S5M8767_REG_BUCK2DVS8,
+ S5M8767_REG_BUCK3CTRL,
+ S5M8767_REG_BUCK3DVS1,
+ S5M8767_REG_BUCK3DVS2,
+ S5M8767_REG_BUCK3DVS3,
+ S5M8767_REG_BUCK3DVS4,
+ S5M8767_REG_BUCK3DVS5,
+ S5M8767_REG_BUCK3DVS6,
+ S5M8767_REG_BUCK3DVS7,
+ S5M8767_REG_BUCK3DVS8,
+ S5M8767_REG_BUCK4CTRL,
+ S5M8767_REG_BUCK4DVS1,
+ S5M8767_REG_BUCK4DVS2,
+ S5M8767_REG_BUCK4DVS3,
+ S5M8767_REG_BUCK4DVS4,
+ S5M8767_REG_BUCK4DVS5,
+ S5M8767_REG_BUCK4DVS6,
+ S5M8767_REG_BUCK4DVS7,
+ S5M8767_REG_BUCK4DVS8,
+ S5M8767_REG_BUCK5CTRL1,
+ S5M8767_REG_BUCK5CTRL2,
+ S5M8767_REG_BUCK6CTRL1,
+ S5M8767_REG_BUCK6CTRL2,
+ S5M8767_REG_BUCK7CTRL1,
+ S5M8767_REG_BUCK7CTRL2,
+ S5M8767_REG_BUCK8CTRL1,
+ S5M8767_REG_BUCK8CTRL2,
+ S5M8767_REG_LDO1CTRL,
+ S5M8767_REG_LDO2CTRL,
+ S5M8767_REG_LDO3CTRL,
+ S5M8767_REG_LDO4CTRL,
+ S5M8767_REG_LDO5CTRL,
+ S5M8767_REG_LDO6CTRL,
+ S5M8767_REG_LDO7CTRL,
+ S5M8767_REG_LDO8CTRL,
+ S5M8767_REG_LDO9CTRL,
+ S5M8767_REG_LDO10CTRL,
+ S5M8767_REG_LDO11CTRL,
+ S5M8767_REG_LDO12CTRL,
+ S5M8767_REG_LDO13CTRL,
+ S5M8767_REG_LDO14CTRL,
+ S5M8767_REG_LDO15CTRL,
+ S5M8767_REG_LDO16CTRL,
+ S5M8767_REG_LDO17CTRL,
+ S5M8767_REG_LDO18CTRL,
+ S5M8767_REG_LDO19CTRL,
+ S5M8767_REG_LDO20CTRL,
+ S5M8767_REG_LDO21CTRL,
+ S5M8767_REG_LDO22CTRL,
+ S5M8767_REG_LDO23CTRL,
+ S5M8767_REG_LDO24CTRL,
+ S5M8767_REG_LDO25CTRL,
+ S5M8767_REG_LDO26CTRL,
+ S5M8767_REG_LDO27CTRL,
+};
+
+/* S5M8763 registers */
+enum s5m8763_reg {
+ S5M8763_REG_IRQ1,
+ S5M8763_REG_IRQ2,
+ S5M8763_REG_IRQ3,
+ S5M8763_REG_IRQ4,
+ S5M8763_REG_IRQM1,
+ S5M8763_REG_IRQM2,
+ S5M8763_REG_IRQM3,
+ S5M8763_REG_IRQM4,
+ S5M8763_REG_STATUS1,
+ S5M8763_REG_STATUS2,
+ S5M8763_REG_STATUSM1,
+ S5M8763_REG_STATUSM2,
+ S5M8763_REG_CHGR1,
+ S5M8763_REG_CHGR2,
+ S5M8763_REG_LDO_ACTIVE_DISCHARGE1,
+ S5M8763_REG_LDO_ACTIVE_DISCHARGE2,
+ S5M8763_REG_BUCK_ACTIVE_DISCHARGE3,
+ S5M8763_REG_ONOFF1,
+ S5M8763_REG_ONOFF2,
+ S5M8763_REG_ONOFF3,
+ S5M8763_REG_ONOFF4,
+ S5M8763_REG_BUCK1_VOLTAGE1,
+ S5M8763_REG_BUCK1_VOLTAGE2,
+ S5M8763_REG_BUCK1_VOLTAGE3,
+ S5M8763_REG_BUCK1_VOLTAGE4,
+ S5M8763_REG_BUCK2_VOLTAGE1,
+ S5M8763_REG_BUCK2_VOLTAGE2,
+ S5M8763_REG_BUCK3,
+ S5M8763_REG_BUCK4,
+ S5M8763_REG_LDO1_LDO2,
+ S5M8763_REG_LDO3,
+ S5M8763_REG_LDO4,
+ S5M8763_REG_LDO5,
+ S5M8763_REG_LDO6,
+ S5M8763_REG_LDO7,
+ S5M8763_REG_LDO7_LDO8,
+ S5M8763_REG_LDO9_LDO10,
+ S5M8763_REG_LDO11,
+ S5M8763_REG_LDO12,
+ S5M8763_REG_LDO13,
+ S5M8763_REG_LDO14,
+ S5M8763_REG_LDO15,
+ S5M8763_REG_LDO16,
+ S5M8763_REG_BKCHR,
+ S5M8763_REG_LBCNFG1,
+ S5M8763_REG_LBCNFG2,
+};
+
+enum s5m8767_irq {
+ S5M8767_IRQ_PWRR,
+ S5M8767_IRQ_PWRF,
+ S5M8767_IRQ_PWR1S,
+ S5M8767_IRQ_JIGR,
+ S5M8767_IRQ_JIGF,
+ S5M8767_IRQ_LOWBAT2,
+ S5M8767_IRQ_LOWBAT1,
+
+ S5M8767_IRQ_MRB,
+ S5M8767_IRQ_DVSOK2,
+ S5M8767_IRQ_DVSOK3,
+ S5M8767_IRQ_DVSOK4,
+
+ S5M8767_IRQ_RTC60S,
+ S5M8767_IRQ_RTCA1,
+ S5M8767_IRQ_RTCA2,
+ S5M8767_IRQ_SMPL,
+ S5M8767_IRQ_RTC1S,
+ S5M8767_IRQ_WTSR,
+
+ S5M8767_IRQ_NR,
+};
+
+#define S5M8767_IRQ_PWRR_MASK (1 << 0)
+#define S5M8767_IRQ_PWRF_MASK (1 << 1)
+#define S5M8767_IRQ_PWR1S_MASK (1 << 3)
+#define S5M8767_IRQ_JIGR_MASK (1 << 4)
+#define S5M8767_IRQ_JIGF_MASK (1 << 5)
+#define S5M8767_IRQ_LOWBAT2_MASK (1 << 6)
+#define S5M8767_IRQ_LOWBAT1_MASK (1 << 7)
+
+#define S5M8767_IRQ_MRB_MASK (1 << 2)
+#define S5M8767_IRQ_DVSOK2_MASK (1 << 3)
+#define S5M8767_IRQ_DVSOK3_MASK (1 << 4)
+#define S5M8767_IRQ_DVSOK4_MASK (1 << 5)
+
+#define S5M8767_IRQ_RTC60S_MASK (1 << 0)
+#define S5M8767_IRQ_RTCA1_MASK (1 << 1)
+#define S5M8767_IRQ_RTCA2_MASK (1 << 2)
+#define S5M8767_IRQ_SMPL_MASK (1 << 3)
+#define S5M8767_IRQ_RTC1S_MASK (1 << 4)
+#define S5M8767_IRQ_WTSR_MASK (1 << 5)
+
+enum s5m8763_irq {
+ S5M8763_IRQ_VDCINF,
+ S5M8763_IRQ_VDCINR,
+ S5M8763_IRQ_JIGF,
+ S5M8763_IRQ_JIGR,
+ S5M8763_IRQ_PWRONF,
+ S5M8763_IRQ_PWRONR,
+
+ S5M8763_IRQ_WTSREVNT,
+ S5M8763_IRQ_SMPLEVNT,
+ S5M8763_IRQ_ALARM1,
+ S5M8763_IRQ_ALARM0,
+
+ S5M8763_IRQ_ONKEY1S,
+ S5M8763_IRQ_TOPOFFR,
+ S5M8763_IRQ_VDCINOVPR,
+ S5M8763_IRQ_CHGRSTF,
+ S5M8763_IRQ_DONER,
+ S5M8763_IRQ_CHGFAULT,
+
+ S5M8763_IRQ_LOBAT1,
+ S5M8763_IRQ_LOBAT2,
+
+ S5M8763_IRQ_NR,
+};
+
+#define S5M8763_IRQ_VDCINF_MASK (1 << 2)
+#define S5M8763_IRQ_VDCINR_MASK (1 << 3)
+#define S5M8763_IRQ_JIGF_MASK (1 << 4)
+#define S5M8763_IRQ_JIGR_MASK (1 << 5)
+#define S5M8763_IRQ_PWRONF_MASK (1 << 6)
+#define S5M8763_IRQ_PWRONR_MASK (1 << 7)
+
+#define S5M8763_IRQ_WTSREVNT_MASK (1 << 0)
+#define S5M8763_IRQ_SMPLEVNT_MASK (1 << 1)
+#define S5M8763_IRQ_ALARM1_MASK (1 << 2)
+#define S5M8763_IRQ_ALARM0_MASK (1 << 3)
+
+#define S5M8763_IRQ_ONKEY1S_MASK (1 << 0)
+#define S5M8763_IRQ_TOPOFFR_MASK (1 << 2)
+#define S5M8763_IRQ_VDCINOVPR_MASK (1 << 3)
+#define S5M8763_IRQ_CHGRSTF_MASK (1 << 4)
+#define S5M8763_IRQ_DONER_MASK (1 << 5)
+#define S5M8763_IRQ_CHGFAULT_MASK (1 << 7)
+
+#define S5M8763_IRQ_LOBAT1_MASK (1 << 0)
+#define S5M8763_IRQ_LOBAT2_MASK (1 << 1)
+
+#define S5M8763_ENRAMP (1 << 4)
+
+struct s5m87xx_dev {
+ struct device *dev;
+ struct i2c_client *i2c;
+ struct i2c_client *rtc;
+ struct mutex irqlock;
+ struct mutex iolock;
+
+ int device_type;
+ int irq_base;
+ int irq;
+ int ono;
+ u8 irq_masks_cur[NUM_IRQ_REGS];
+ u8 irq_masks_cache[NUM_IRQ_REGS];
+ int type;
+ bool wakeup;
+
+ struct regmap *regmap;
+};
+
+int s5m_irq_init(struct s5m87xx_dev *s5m87xx);
+void s5m_irq_exit(struct s5m87xx_dev *s5m87xx);
+int s5m_irq_resume(struct s5m87xx_dev *s5m87xx);
+
+extern int s5m_reg_read(struct s5m87xx_dev *s5m87xx, u8 reg, u8 *dest);
+extern int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count,u8 *buf);
+extern int s5m_reg_write(struct s5m87xx_dev *s5m87xx, u8 reg, u8 value);
+extern int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count,u8 *buf);
+extern int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask);
+
+#endif /* __LINUX_MFD_S5M_CORE_H */
diff --git a/include/linux/mfd/s5m87xx/s5m-pmic.h b/include/linux/mfd/s5m87xx/s5m-pmic.h
new file mode 100644
index 0000000..2bb57b3
--- /dev/null
+++ b/include/linux/mfd/s5m87xx/s5m-pmic.h
@@ -0,0 +1,141 @@
+/*
+ * s5m-pmic.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_S5M_PMIC_H
+#define __LINUX_MFD_S5M_PMIC_H
+
+#include <linux/regulator/machine.h>
+
+/* S5M8767 regulator ids */
+enum s5m8767_regulators {
+ S5M8767_LDO1,
+ S5M8767_LDO2,
+ S5M8767_LDO3,
+ S5M8767_LDO4,
+ S5M8767_LDO5,
+ S5M8767_LDO6,
+ S5M8767_LDO7,
+ S5M8767_LDO8,
+ S5M8767_LDO9,
+ S5M8767_LDO10,
+ S5M8767_LDO11,
+ S5M8767_LDO12,
+ S5M8767_LDO13,
+ S5M8767_LDO14,
+ S5M8767_LDO15,
+ S5M8767_LDO16,
+ S5M8767_LDO17,
+ S5M8767_LDO18,
+ S5M8767_LDO19,
+ S5M8767_LDO20,
+ S5M8767_LDO21,
+ S5M8767_LDO22,
+ S5M8767_LDO23,
+ S5M8767_LDO24,
+ S5M8767_LDO25,
+ S5M8767_LDO26,
+ S5M8767_LDO27,
+ S5M8767_BUCK1,
+ S5M8767_BUCK2,
+ S5M8767_BUCK3,
+ S5M8767_BUCK4,
+ S5M8767_BUCK5,
+ S5M8767_BUCK6,
+ S5M8767_BUCK7,
+ S5M8767_BUCK8,
+ S5M8767_32KHZAP_EN,
+ S5M8767_32KHZCP_EN,
+
+ S5M8767_REG_MAX,
+};
+
+/* S5M8763 regulator ids */
+enum s5m8763_regulators {
+ S5M8763_LDO1,
+ S5M8763_LDO2,
+ S5M8763_LDO3,
+ S5M8763_LDO4,
+ S5M8763_LDO5,
+ S5M8763_LDO6,
+ S5M8763_LDO7,
+ S5M8763_LDO8,
+ S5M8763_LDO9,
+ S5M8763_LDO10,
+ S5M8763_LDO11,
+ S5M8763_LDO12,
+ S5M8763_LDO13,
+ S5M8763_LDO14,
+ S5M8763_LDO15,
+ S5M8763_LDO16,
+ S5M8763_BUCK1,
+ S5M8763_BUCK2,
+ S5M8763_BUCK3,
+ S5M8763_BUCK4,
+ S5M8763_AP_EN32KHZ,
+ S5M8763_CP_EN32KHZ,
+ S5M8763_ENCHGVI,
+ S5M8763_ESAFEUSB1,
+ S5M8763_ESAFEUSB2,
+};
+
+/**
+ * s5m87xx_regulator_data - regulator data
+ * @id: regulator id
+ * @initdata: regulator init data (contraints, supplies, ...)
+ */
+struct s5m87xx_regulator_data {
+ int id;
+ struct regulator_init_data *initdata;
+};
+
+struct s5m87xx_platform_data {
+ struct s5m87xx_regulator_data *regulators;
+ int device_type;
+ int num_regulators;
+ int irq_base;
+ int ono;
+ bool wakeup;
+ bool buck_voltage_lock;
+
+ int buck_gpios[3];
+ int buck_default_idx;
+ int buck1_voltage[4];
+ int buck2_voltage[8];
+ bool buck2_gpiodvs;
+ int buck3_voltage[8];
+ bool buck3_gpiodvs;
+ int buck4_voltage[8];
+ bool buck4_gpiodvs;
+
+ int buck1_set1;
+ int buck1_set2;
+ int buck2_set3;
+ int buck_set1;
+ int buck_set2;
+ int buck_set3;
+ int buck2_enable;
+ int buck3_enable;
+ int buck4_enable;
+ int buck1_default_idx;
+ int buck2_default_idx;
+ int buck3_default_idx;
+ int buck4_default_idx;
+ int buck_ramp_delay;
+ bool buck2_ramp_enable;
+ bool buck3_ramp_enable;
+ bool buck4_ramp_enable;
+
+
+};
+
+#endif /* __LINUX_MFD_S5M_PMIC_H */
diff --git a/include/linux/mfd/s5m87xx/s5m-rtc.h b/include/linux/mfd/s5m87xx/s5m-rtc.h
new file mode 100644
index 0000000..6f52e3c
--- /dev/null
+++ b/include/linux/mfd/s5m87xx/s5m-rtc.h
@@ -0,0 +1,69 @@
+/*
+ * s5m-rtc.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_S5M_RTC_H
+#define __LINUX_MFD_S5M_RTC_H
+
+enum s5m_rtc_reg {
+ S5M_RTC_SEC,
+ S5M_RTC_MIN,
+ S5M_RTC_HOUR,
+ S5M_RTC_WEEKDAY,
+ S5M_RTC_DATE,
+ S5M_RTC_MONTH,
+ S5M_RTC_YEAR1,
+ S5M_RTC_YEAR2,
+ S5M_ALARM0_SEC,
+ S5M_ALARM0_MIN,
+ S5M_ALARM0_HOUR,
+ S5M_ALARM0_WEEKDAY,
+ S5M_ALARM0_DATE,
+ S5M_ALARM0_MONTH,
+ S5M_ALARM0_YEAR1,
+ S5M_ALARM0_YEAR2,
+ S5M_ALARM1_SEC,
+ S5M_ALARM1_MIN,
+ S5M_ALARM1_HOUR,
+ S5M_ALARM1_WEEKDAY,
+ S5M_ALARM1_DATE,
+ S5M_ALARM1_MONTH,
+ S5M_ALARM1_YEAR1,
+ S5M_ALARM1_YEAR2,
+ S5M_ALARM0_CONF,
+ S5M_ALARM1_CONF,
+ S5M_RTC_STATUS,
+ S5M_WTSR_SMPL_CNTL,
+ S5M_RTC_UDR_CON,
+};
+
+#define RTC_I2C_ADDR (0x0C >> 1)
+
+#define HOUR_12 (1 << 7)
+#define HOUR_AMPM (1 << 6)
+#define HOUR_PM (1 << 5)
+#define ALARM0_STATUS (1 << 1)
+#define ALARM1_STATUS (1 << 2)
+#define UPDATE_AD (1 << 0)
+
+enum {
+ RTC_SEC = 0,
+ RTC_MIN,
+ RTC_HOUR,
+ RTC_WEEKDAY,
+ RTC_DATE,
+ RTC_MONTH,
+ RTC_YEAR1,
+ RTC_YEAR2,
+};
+
+#endif /* __LINUX_MFD_S5M_RTC_H */
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 13/X] uprobes: introduce UTASK_SSTEP_TRAPPED logic
From: Ananth N Mavinakayanahalli @ 2011-10-24 15:16 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Srikar Dronamraju, Peter Zijlstra, Ingo Molnar, Steven Rostedt,
Linux-mm, Arnaldo Carvalho de Melo, Linus Torvalds,
Jonathan Corbet, Masami Hiramatsu, Hugh Dickins,
Christoph Hellwig, Thomas Gleixner, Andi Kleen, Andrew Morton,
Jim Keniston, Roland McGrath, LKML
In-Reply-To: <20111024144127.GA14975@redhat.com>
On Mon, Oct 24, 2011 at 04:41:27PM +0200, Oleg Nesterov wrote:
> On 10/22, Ananth N Mavinakayanahalli wrote:
> >
> > On Wed, Oct 19, 2011 at 11:53:44PM +0200, Oleg Nesterov wrote:
> > > Finally, add UTASK_SSTEP_TRAPPED state/code to handle the case when
> > > xol insn itself triggers the signal.
> > >
> > > In this case we should restart the original insn even if the task is
> > > already SIGKILL'ed (say, the coredump should report the correct ip).
> > > This is even more important if the task has a handler for SIGSEGV/etc,
> > > The _same_ instruction should be repeated again after return from the
> > > signal handler, and SSTEP can never finish in this case.
> >
> > Oleg,
> >
> > Not sure I understand this completely...
>
> I hope you do not think I do ;)
I think you understand it better than you think you do :-)
> > When you say 'correct ip' you mean the original vaddr where we now have
> > a uprobe breakpoint and not the xol copy, right?
>
> Yes,
>
> > Coredump needs to report the correct ip, but should it also not report
> > correctly the instruction that caused the signal? Ergo, shouldn't we
> > put the original instruction back at the uprobed vaddr?
>
> OK, now I see what you mean. I was confused by the "restore the original
> instruction before _restart_" suggestion.
>
> Agreed! it would be nice to "hide" these int3's if we dump the core, but
> I think this is a bit off-topic. It makes sense to do this in any case,
> even if the core-dumping was triggered by another thread/insn. It makes
> sense to remove all int3's, not only at regs->ip location. But how can
> we do this? This is nontrivial.
I don't think that is a problem.. see below...
> And. Even worse. Suppose that you do "gdb probed_application". Now you
> see int3's in the disassemble output. What can we do?
In this case, nothing.
> I think we can do nothing, at least currently. This just reflects the
> fact that uprobe connects to inode, not to process/mm/etc.
>
> What do you think?
Thinking further on this, in the normal 'running gdb on a core' case, we
won't have this problem, as the binary that we point gdb to, will be a
pristine one, without the uprobe int3s, right?
Ananth
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH 11/X] uprobes: x86: introduce xol_was_trapped()
From: Srikar Dronamraju @ 2011-10-24 14:55 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Peter Zijlstra, Ingo Molnar, Steven Rostedt, Linux-mm,
Arnaldo Carvalho de Melo, Linus Torvalds, Jonathan Corbet,
Masami Hiramatsu, Hugh Dickins, Christoph Hellwig,
Ananth N Mavinakayanahalli, Thomas Gleixner, Andi Kleen,
Andrew Morton, Jim Keniston, Roland McGrath, LKML
In-Reply-To: <20111019215307.GE16395@redhat.com>
> diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
> index 1c30cfd..f0fbdab 100644
> --- a/arch/x86/include/asm/uprobes.h
> +++ b/arch/x86/include/asm/uprobes.h
> @@ -39,6 +39,7 @@ struct uprobe_arch_info {
>
> struct uprobe_task_arch_info {
> unsigned long saved_scratch_register;
> + unsigned long saved_trap_no;
> };
> #else
> struct uprobe_arch_info {};
one nit
I had to add saved_trap_no to #else part (i.e uprobe_arch_info ).
--
Thanks and Regards
Srikar
^ permalink raw reply
* [PATCH 1/3] mfd: Add S5M core driver
From: Sangbeom Kim @ 2011-10-23 7:30 UTC (permalink / raw)
To: sameo; +Cc: linux-kernel, broonie, Sangbeom Kim
In-Reply-To: <1319355002-12674-1-git-send-email-sbkim73@samsung.com>
S5M series are pmic including mutiple functions.
It can support PMIC, RTC, Battery charger, codec.
This patch implement core driver for s5m series.
Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
---
drivers/mfd/s5m-core.c | 235 +++++++++++++++++++++++++
include/linux/mfd/s5m87xx/s5m-core.h | 313 ++++++++++++++++++++++++++++++++++
include/linux/mfd/s5m87xx/s5m-pmic.h | 141 +++++++++++++++
include/linux/mfd/s5m87xx/s5m-rtc.h | 69 ++++++++
4 files changed, 758 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/s5m-core.c
create mode 100644 include/linux/mfd/s5m87xx/s5m-core.h
create mode 100644 include/linux/mfd/s5m87xx/s5m-pmic.h
create mode 100644 include/linux/mfd/s5m87xx/s5m-rtc.h
diff --git a/drivers/mfd/s5m-core.c b/drivers/mfd/s5m-core.c
new file mode 100644
index 0000000..6dac3a1
--- /dev/null
+++ b/drivers/mfd/s5m-core.c
@@ -0,0 +1,235 @@
+/*
+ * s5m-core.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/mutex.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/s5m87xx/s5m-core.h>
+#include <linux/mfd/s5m87xx/s5m-pmic.h>
+#include <linux/mfd/s5m87xx/s5m-rtc.h>
+#include <linux/regmap.h>
+
+int s5m_reg_read(struct s5m87xx_dev *s5m87xx, u8 reg, u8 *dest)
+{
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(s5m87xx->regmap, reg, &val);
+
+ if (ret < 0)
+ return ret;
+
+ ret &= 0xff;
+ *dest = ret;
+ return 0;
+}
+EXPORT_SYMBOL(s5m_reg_read);
+
+int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
+{
+ int ret;
+
+ ret = regmap_bulk_read(s5m87xx->regmap, reg, buf, count);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(s5m_bulk_read);
+
+int s5m_reg_write(struct s5m87xx_dev *s5m87xx, u8 reg, u8 value)
+{
+ int ret;
+
+ ret = regmap_write(s5m87xx->regmap, reg, value);
+ return ret;
+}
+EXPORT_SYMBOL(s5m_reg_write);
+
+int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf)
+{
+ int ret;
+
+ ret = regmap_raw_write(s5m87xx->regmap, reg, buf, count * sizeof(u16));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(s5m_bulk_write);
+
+int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask)
+{
+ int ret;
+
+ ret = regmap_update_bits(s5m87xx->regmap, reg, mask, val);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+EXPORT_SYMBOL(s5m_reg_update);
+
+static struct mfd_cell s5m87xx_devs[] = {
+ {
+ .name = "s5m8763-pmic",
+ }, {
+ .name = "s5m8767-pmic",
+ }, {
+ .name = "s5m-rtc",
+ }, {
+ .name = "s5m8763-charger",
+ },
+};
+
+static struct regmap_config s5m_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int s5m_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct s5m87xx_platform_data *pdata = i2c->dev.platform_data;
+ struct s5m87xx_dev *s5m87xx;
+ int ret = 0;
+ int error;
+
+ s5m87xx = kzalloc(sizeof(struct s5m87xx_dev), GFP_KERNEL);
+ if (s5m87xx == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, s5m87xx);
+ s5m87xx->dev = &i2c->dev;
+ s5m87xx->i2c = i2c;
+ s5m87xx->irq = i2c->irq;
+ s5m87xx->type = id->driver_data;
+
+ if (pdata) {
+ s5m87xx->device_type = pdata->device_type;
+ s5m87xx->ono = pdata->ono;
+ s5m87xx->irq_base = pdata->irq_base;
+ s5m87xx->wakeup = pdata->wakeup;
+ }
+
+ s5m87xx->regmap = regmap_init_i2c(i2c, &s5m_regmap_config);
+ if (IS_ERR(s5m87xx->regmap)) {
+ error = PTR_ERR(s5m87xx->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ error);
+ goto err;
+ }
+
+ s5m87xx->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
+ i2c_set_clientdata(s5m87xx->rtc, s5m87xx);
+
+ s5m_irq_init(s5m87xx);
+
+ pm_runtime_set_active(s5m87xx->dev);
+
+ ret = mfd_add_devices(s5m87xx->dev, -1,
+ s5m87xx_devs, ARRAY_SIZE(s5m87xx_devs),
+ NULL, 0);
+ if (ret < 0)
+ goto err;
+
+ dev_info(s5m87xx->dev ,"SAMSUNG S5M MFD\n");
+ return ret;
+
+err:
+ mfd_remove_devices(s5m87xx->dev);
+ s5m_irq_exit(s5m87xx);
+ i2c_unregister_device(s5m87xx->rtc);
+ regmap_exit(s5m87xx->regmap);
+ kfree(s5m87xx);
+ return ret;
+}
+
+static int s5m_i2c_remove(struct i2c_client *i2c)
+{
+ struct s5m87xx_dev *s5m87xx = i2c_get_clientdata(i2c);
+
+ mfd_remove_devices(s5m87xx->dev);
+ s5m_irq_exit(s5m87xx);
+ i2c_unregister_device(s5m87xx->rtc);
+ regmap_exit(s5m87xx->regmap);
+ kfree(s5m87xx);
+
+ return 0;
+}
+
+static const struct i2c_device_id s5m87xx_i2c_id[] = {
+ { "s5m87xx", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, s5m87xx_i2c_id);
+
+static int s5m_suspend(struct i2c_client *i2c, pm_message_t state)
+{
+ struct s5m87xx_dev *s5m87xx = i2c_get_clientdata(i2c);
+
+ if (s5m87xx->wakeup)
+ enable_irq_wake(s5m87xx->irq);
+
+ disable_irq(s5m87xx->irq);
+
+ return 0;
+}
+
+static int s5m_resume(struct i2c_client *i2c)
+{
+ struct s5m87xx_dev *s5m87xx = i2c_get_clientdata(i2c);
+
+ if (s5m87xx->wakeup)
+ disable_irq_wake(s5m87xx->irq);
+
+ enable_irq(s5m87xx->irq);
+
+ return 0;
+}
+
+static struct i2c_driver s5m87xx_i2c_driver = {
+ .driver = {
+ .name = "s5m87xx",
+ .owner = THIS_MODULE,
+ },
+ .probe = s5m_i2c_probe,
+ .remove = s5m_i2c_remove,
+ .id_table = s5m87xx_i2c_id,
+ .suspend = s5m_suspend,
+ .resume = s5m_resume,
+};
+
+static int __init s5m87xx_i2c_init(void)
+{
+ return i2c_add_driver(&s5m87xx_i2c_driver);
+}
+
+subsys_initcall(s5m87xx_i2c_init);
+
+static void __exit s5m87xx_i2c_exit(void)
+{
+ i2c_del_driver(&s5m87xx_i2c_driver);
+}
+module_exit(s5m87xx_i2c_exit);
+
+MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
+MODULE_DESCRIPTION("Core support for the S5M87XX MFD");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/s5m87xx/s5m-core.h b/include/linux/mfd/s5m87xx/s5m-core.h
new file mode 100644
index 0000000..ddacd5b
--- /dev/null
+++ b/include/linux/mfd/s5m87xx/s5m-core.h
@@ -0,0 +1,313 @@
+/*
+ * s5m-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_S5M_CORE_H
+#define __LINUX_MFD_S5M_CORE_H
+
+#define NUM_IRQ_REGS 4
+
+enum s5m_device_type {
+ S5M8751X,
+ S5M8763X,
+ S5M8767X,
+};
+
+/* S5M8767 registers */
+enum s5m8767_reg {
+ S5M8767_REG_ID,
+ S5M8767_REG_INT1,
+ S5M8767_REG_INT2,
+ S5M8767_REG_INT3,
+ S5M8767_REG_INT1M,
+ S5M8767_REG_INT2M,
+ S5M8767_REG_INT3M,
+ S5M8767_REG_STATUS1,
+ S5M8767_REG_STATUS2,
+ S5M8767_REG_STATUS3,
+ S5M8767_REG_CTRL1,
+ S5M8767_REG_CTRL2,
+ S5M8767_REG_LOWBAT1,
+ S5M8767_REG_LOWBAT2,
+ S5M8767_REG_BUCHG,
+ S5M8767_REG_DVSRAMP,
+ S5M8767_REG_DVSTIMER1,
+ S5M8767_REG_DVSTIMER2,
+ S5M8767_REG_DVSTIMER3,
+ S5M8767_REG_DVSTIMER4,
+ S5M8767_REG_LDO1,
+ S5M8767_REG_LDO2,
+ S5M8767_REG_LDO3,
+ S5M8767_REG_LDO4,
+ S5M8767_REG_LDO5,
+ S5M8767_REG_LDO6,
+ S5M8767_REG_LDO7,
+ S5M8767_REG_LDO8,
+ S5M8767_REG_LDO9,
+ S5M8767_REG_LDO10,
+ S5M8767_REG_LDO11,
+ S5M8767_REG_LDO12,
+ S5M8767_REG_LDO13,
+ S5M8767_REG_LDO14,
+ S5M8767_REG_LDO15,
+ S5M8767_REG_LDO16,
+ S5M8767_REG_LDO17,
+ S5M8767_REG_LDO18,
+ S5M8767_REG_LDO19,
+ S5M8767_REG_LDO20,
+ S5M8767_REG_LDO21,
+ S5M8767_REG_LDO22,
+ S5M8767_REG_LDO23,
+ S5M8767_REG_LDO24,
+ S5M8767_REG_LDO25,
+ S5M8767_REG_LDO26,
+ S5M8767_REG_LDO27,
+ S5M8767_REG_BUCK1CTRL1 = 0x35,
+ S5M8767_REG_BUCK1CTRL2,
+ S5M8767_REG_BUCK2CTRL,
+ S5M8767_REG_BUCK2DVS1,
+ S5M8767_REG_BUCK2DVS2,
+ S5M8767_REG_BUCK2DVS3,
+ S5M8767_REG_BUCK2DVS4,
+ S5M8767_REG_BUCK2DVS5,
+ S5M8767_REG_BUCK2DVS6,
+ S5M8767_REG_BUCK2DVS7,
+ S5M8767_REG_BUCK2DVS8,
+ S5M8767_REG_BUCK3CTRL,
+ S5M8767_REG_BUCK3DVS1,
+ S5M8767_REG_BUCK3DVS2,
+ S5M8767_REG_BUCK3DVS3,
+ S5M8767_REG_BUCK3DVS4,
+ S5M8767_REG_BUCK3DVS5,
+ S5M8767_REG_BUCK3DVS6,
+ S5M8767_REG_BUCK3DVS7,
+ S5M8767_REG_BUCK3DVS8,
+ S5M8767_REG_BUCK4CTRL,
+ S5M8767_REG_BUCK4DVS1,
+ S5M8767_REG_BUCK4DVS2,
+ S5M8767_REG_BUCK4DVS3,
+ S5M8767_REG_BUCK4DVS4,
+ S5M8767_REG_BUCK4DVS5,
+ S5M8767_REG_BUCK4DVS6,
+ S5M8767_REG_BUCK4DVS7,
+ S5M8767_REG_BUCK4DVS8,
+ S5M8767_REG_BUCK5CTRL1,
+ S5M8767_REG_BUCK5CTRL2,
+ S5M8767_REG_BUCK6CTRL1,
+ S5M8767_REG_BUCK6CTRL2,
+ S5M8767_REG_BUCK7CTRL1,
+ S5M8767_REG_BUCK7CTRL2,
+ S5M8767_REG_BUCK8CTRL1,
+ S5M8767_REG_BUCK8CTRL2,
+ S5M8767_REG_LDO1CTRL,
+ S5M8767_REG_LDO2CTRL,
+ S5M8767_REG_LDO3CTRL,
+ S5M8767_REG_LDO4CTRL,
+ S5M8767_REG_LDO5CTRL,
+ S5M8767_REG_LDO6CTRL,
+ S5M8767_REG_LDO7CTRL,
+ S5M8767_REG_LDO8CTRL,
+ S5M8767_REG_LDO9CTRL,
+ S5M8767_REG_LDO10CTRL,
+ S5M8767_REG_LDO11CTRL,
+ S5M8767_REG_LDO12CTRL,
+ S5M8767_REG_LDO13CTRL,
+ S5M8767_REG_LDO14CTRL,
+ S5M8767_REG_LDO15CTRL,
+ S5M8767_REG_LDO16CTRL,
+ S5M8767_REG_LDO17CTRL,
+ S5M8767_REG_LDO18CTRL,
+ S5M8767_REG_LDO19CTRL,
+ S5M8767_REG_LDO20CTRL,
+ S5M8767_REG_LDO21CTRL,
+ S5M8767_REG_LDO22CTRL,
+ S5M8767_REG_LDO23CTRL,
+ S5M8767_REG_LDO24CTRL,
+ S5M8767_REG_LDO25CTRL,
+ S5M8767_REG_LDO26CTRL,
+ S5M8767_REG_LDO27CTRL,
+};
+
+/* S5M8763 registers */
+enum s5m8763_reg {
+ S5M8763_REG_IRQ1,
+ S5M8763_REG_IRQ2,
+ S5M8763_REG_IRQ3,
+ S5M8763_REG_IRQ4,
+ S5M8763_REG_IRQM1,
+ S5M8763_REG_IRQM2,
+ S5M8763_REG_IRQM3,
+ S5M8763_REG_IRQM4,
+ S5M8763_REG_STATUS1,
+ S5M8763_REG_STATUS2,
+ S5M8763_REG_STATUSM1,
+ S5M8763_REG_STATUSM2,
+ S5M8763_REG_CHGR1,
+ S5M8763_REG_CHGR2,
+ S5M8763_REG_LDO_ACTIVE_DISCHARGE1,
+ S5M8763_REG_LDO_ACTIVE_DISCHARGE2,
+ S5M8763_REG_BUCK_ACTIVE_DISCHARGE3,
+ S5M8763_REG_ONOFF1,
+ S5M8763_REG_ONOFF2,
+ S5M8763_REG_ONOFF3,
+ S5M8763_REG_ONOFF4,
+ S5M8763_REG_BUCK1_VOLTAGE1,
+ S5M8763_REG_BUCK1_VOLTAGE2,
+ S5M8763_REG_BUCK1_VOLTAGE3,
+ S5M8763_REG_BUCK1_VOLTAGE4,
+ S5M8763_REG_BUCK2_VOLTAGE1,
+ S5M8763_REG_BUCK2_VOLTAGE2,
+ S5M8763_REG_BUCK3,
+ S5M8763_REG_BUCK4,
+ S5M8763_REG_LDO1_LDO2,
+ S5M8763_REG_LDO3,
+ S5M8763_REG_LDO4,
+ S5M8763_REG_LDO5,
+ S5M8763_REG_LDO6,
+ S5M8763_REG_LDO7,
+ S5M8763_REG_LDO7_LDO8,
+ S5M8763_REG_LDO9_LDO10,
+ S5M8763_REG_LDO11,
+ S5M8763_REG_LDO12,
+ S5M8763_REG_LDO13,
+ S5M8763_REG_LDO14,
+ S5M8763_REG_LDO15,
+ S5M8763_REG_LDO16,
+ S5M8763_REG_BKCHR,
+ S5M8763_REG_LBCNFG1,
+ S5M8763_REG_LBCNFG2,
+};
+
+enum s5m8767_irq {
+ S5M8767_IRQ_PWRR,
+ S5M8767_IRQ_PWRF,
+ S5M8767_IRQ_PWR1S,
+ S5M8767_IRQ_JIGR,
+ S5M8767_IRQ_JIGF,
+ S5M8767_IRQ_LOWBAT2,
+ S5M8767_IRQ_LOWBAT1,
+
+ S5M8767_IRQ_MRB,
+ S5M8767_IRQ_DVSOK2,
+ S5M8767_IRQ_DVSOK3,
+ S5M8767_IRQ_DVSOK4,
+
+ S5M8767_IRQ_RTC60S,
+ S5M8767_IRQ_RTCA1,
+ S5M8767_IRQ_RTCA2,
+ S5M8767_IRQ_SMPL,
+ S5M8767_IRQ_RTC1S,
+ S5M8767_IRQ_WTSR,
+
+ S5M8767_IRQ_NR,
+};
+
+#define S5M8767_IRQ_PWRR_MASK (1 << 0)
+#define S5M8767_IRQ_PWRF_MASK (1 << 1)
+#define S5M8767_IRQ_PWR1S_MASK (1 << 3)
+#define S5M8767_IRQ_JIGR_MASK (1 << 4)
+#define S5M8767_IRQ_JIGF_MASK (1 << 5)
+#define S5M8767_IRQ_LOWBAT2_MASK (1 << 6)
+#define S5M8767_IRQ_LOWBAT1_MASK (1 << 7)
+
+#define S5M8767_IRQ_MRB_MASK (1 << 2)
+#define S5M8767_IRQ_DVSOK2_MASK (1 << 3)
+#define S5M8767_IRQ_DVSOK3_MASK (1 << 4)
+#define S5M8767_IRQ_DVSOK4_MASK (1 << 5)
+
+#define S5M8767_IRQ_RTC60S_MASK (1 << 0)
+#define S5M8767_IRQ_RTCA1_MASK (1 << 1)
+#define S5M8767_IRQ_RTCA2_MASK (1 << 2)
+#define S5M8767_IRQ_SMPL_MASK (1 << 3)
+#define S5M8767_IRQ_RTC1S_MASK (1 << 4)
+#define S5M8767_IRQ_WTSR_MASK (1 << 5)
+
+enum s5m8763_irq {
+ S5M8763_IRQ_VDCINF,
+ S5M8763_IRQ_VDCINR,
+ S5M8763_IRQ_JIGF,
+ S5M8763_IRQ_JIGR,
+ S5M8763_IRQ_PWRONF,
+ S5M8763_IRQ_PWRONR,
+
+ S5M8763_IRQ_WTSREVNT,
+ S5M8763_IRQ_SMPLEVNT,
+ S5M8763_IRQ_ALARM1,
+ S5M8763_IRQ_ALARM0,
+
+ S5M8763_IRQ_ONKEY1S,
+ S5M8763_IRQ_TOPOFFR,
+ S5M8763_IRQ_VDCINOVPR,
+ S5M8763_IRQ_CHGRSTF,
+ S5M8763_IRQ_DONER,
+ S5M8763_IRQ_CHGFAULT,
+
+ S5M8763_IRQ_LOBAT1,
+ S5M8763_IRQ_LOBAT2,
+
+ S5M8763_IRQ_NR,
+};
+
+#define S5M8763_IRQ_VDCINF_MASK (1 << 2)
+#define S5M8763_IRQ_VDCINR_MASK (1 << 3)
+#define S5M8763_IRQ_JIGF_MASK (1 << 4)
+#define S5M8763_IRQ_JIGR_MASK (1 << 5)
+#define S5M8763_IRQ_PWRONF_MASK (1 << 6)
+#define S5M8763_IRQ_PWRONR_MASK (1 << 7)
+
+#define S5M8763_IRQ_WTSREVNT_MASK (1 << 0)
+#define S5M8763_IRQ_SMPLEVNT_MASK (1 << 1)
+#define S5M8763_IRQ_ALARM1_MASK (1 << 2)
+#define S5M8763_IRQ_ALARM0_MASK (1 << 3)
+
+#define S5M8763_IRQ_ONKEY1S_MASK (1 << 0)
+#define S5M8763_IRQ_TOPOFFR_MASK (1 << 2)
+#define S5M8763_IRQ_VDCINOVPR_MASK (1 << 3)
+#define S5M8763_IRQ_CHGRSTF_MASK (1 << 4)
+#define S5M8763_IRQ_DONER_MASK (1 << 5)
+#define S5M8763_IRQ_CHGFAULT_MASK (1 << 7)
+
+#define S5M8763_IRQ_LOBAT1_MASK (1 << 0)
+#define S5M8763_IRQ_LOBAT2_MASK (1 << 1)
+
+#define S5M8763_ENRAMP (1 << 4)
+
+struct s5m87xx_dev {
+ struct device *dev;
+ struct i2c_client *i2c;
+ struct i2c_client *rtc;
+ struct mutex irqlock;
+ struct mutex iolock;
+
+ int device_type;
+ int irq_base;
+ int irq;
+ int ono;
+ u8 irq_masks_cur[NUM_IRQ_REGS];
+ u8 irq_masks_cache[NUM_IRQ_REGS];
+ int type;
+ bool wakeup;
+
+ struct regmap *regmap;
+};
+
+int s5m_irq_init(struct s5m87xx_dev *s5m87xx);
+void s5m_irq_exit(struct s5m87xx_dev *s5m87xx);
+int s5m_irq_resume(struct s5m87xx_dev *s5m87xx);
+
+extern int s5m_reg_read(struct s5m87xx_dev *s5m87xx, u8 reg, u8 *dest);
+extern int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count,u8 *buf);
+extern int s5m_reg_write(struct s5m87xx_dev *s5m87xx, u8 reg, u8 value);
+extern int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count,u8 *buf);
+extern int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask);
+
+#endif /* __LINUX_MFD_S5M_CORE_H */
diff --git a/include/linux/mfd/s5m87xx/s5m-pmic.h b/include/linux/mfd/s5m87xx/s5m-pmic.h
new file mode 100644
index 0000000..2bb57b3
--- /dev/null
+++ b/include/linux/mfd/s5m87xx/s5m-pmic.h
@@ -0,0 +1,141 @@
+/*
+ * s5m-pmic.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_S5M_PMIC_H
+#define __LINUX_MFD_S5M_PMIC_H
+
+#include <linux/regulator/machine.h>
+
+/* S5M8767 regulator ids */
+enum s5m8767_regulators {
+ S5M8767_LDO1,
+ S5M8767_LDO2,
+ S5M8767_LDO3,
+ S5M8767_LDO4,
+ S5M8767_LDO5,
+ S5M8767_LDO6,
+ S5M8767_LDO7,
+ S5M8767_LDO8,
+ S5M8767_LDO9,
+ S5M8767_LDO10,
+ S5M8767_LDO11,
+ S5M8767_LDO12,
+ S5M8767_LDO13,
+ S5M8767_LDO14,
+ S5M8767_LDO15,
+ S5M8767_LDO16,
+ S5M8767_LDO17,
+ S5M8767_LDO18,
+ S5M8767_LDO19,
+ S5M8767_LDO20,
+ S5M8767_LDO21,
+ S5M8767_LDO22,
+ S5M8767_LDO23,
+ S5M8767_LDO24,
+ S5M8767_LDO25,
+ S5M8767_LDO26,
+ S5M8767_LDO27,
+ S5M8767_BUCK1,
+ S5M8767_BUCK2,
+ S5M8767_BUCK3,
+ S5M8767_BUCK4,
+ S5M8767_BUCK5,
+ S5M8767_BUCK6,
+ S5M8767_BUCK7,
+ S5M8767_BUCK8,
+ S5M8767_32KHZAP_EN,
+ S5M8767_32KHZCP_EN,
+
+ S5M8767_REG_MAX,
+};
+
+/* S5M8763 regulator ids */
+enum s5m8763_regulators {
+ S5M8763_LDO1,
+ S5M8763_LDO2,
+ S5M8763_LDO3,
+ S5M8763_LDO4,
+ S5M8763_LDO5,
+ S5M8763_LDO6,
+ S5M8763_LDO7,
+ S5M8763_LDO8,
+ S5M8763_LDO9,
+ S5M8763_LDO10,
+ S5M8763_LDO11,
+ S5M8763_LDO12,
+ S5M8763_LDO13,
+ S5M8763_LDO14,
+ S5M8763_LDO15,
+ S5M8763_LDO16,
+ S5M8763_BUCK1,
+ S5M8763_BUCK2,
+ S5M8763_BUCK3,
+ S5M8763_BUCK4,
+ S5M8763_AP_EN32KHZ,
+ S5M8763_CP_EN32KHZ,
+ S5M8763_ENCHGVI,
+ S5M8763_ESAFEUSB1,
+ S5M8763_ESAFEUSB2,
+};
+
+/**
+ * s5m87xx_regulator_data - regulator data
+ * @id: regulator id
+ * @initdata: regulator init data (contraints, supplies, ...)
+ */
+struct s5m87xx_regulator_data {
+ int id;
+ struct regulator_init_data *initdata;
+};
+
+struct s5m87xx_platform_data {
+ struct s5m87xx_regulator_data *regulators;
+ int device_type;
+ int num_regulators;
+ int irq_base;
+ int ono;
+ bool wakeup;
+ bool buck_voltage_lock;
+
+ int buck_gpios[3];
+ int buck_default_idx;
+ int buck1_voltage[4];
+ int buck2_voltage[8];
+ bool buck2_gpiodvs;
+ int buck3_voltage[8];
+ bool buck3_gpiodvs;
+ int buck4_voltage[8];
+ bool buck4_gpiodvs;
+
+ int buck1_set1;
+ int buck1_set2;
+ int buck2_set3;
+ int buck_set1;
+ int buck_set2;
+ int buck_set3;
+ int buck2_enable;
+ int buck3_enable;
+ int buck4_enable;
+ int buck1_default_idx;
+ int buck2_default_idx;
+ int buck3_default_idx;
+ int buck4_default_idx;
+ int buck_ramp_delay;
+ bool buck2_ramp_enable;
+ bool buck3_ramp_enable;
+ bool buck4_ramp_enable;
+
+
+};
+
+#endif /* __LINUX_MFD_S5M_PMIC_H */
diff --git a/include/linux/mfd/s5m87xx/s5m-rtc.h b/include/linux/mfd/s5m87xx/s5m-rtc.h
new file mode 100644
index 0000000..6f52e3c
--- /dev/null
+++ b/include/linux/mfd/s5m87xx/s5m-rtc.h
@@ -0,0 +1,69 @@
+/*
+ * s5m-rtc.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __LINUX_MFD_S5M_RTC_H
+#define __LINUX_MFD_S5M_RTC_H
+
+enum s5m_rtc_reg {
+ S5M_RTC_SEC,
+ S5M_RTC_MIN,
+ S5M_RTC_HOUR,
+ S5M_RTC_WEEKDAY,
+ S5M_RTC_DATE,
+ S5M_RTC_MONTH,
+ S5M_RTC_YEAR1,
+ S5M_RTC_YEAR2,
+ S5M_ALARM0_SEC,
+ S5M_ALARM0_MIN,
+ S5M_ALARM0_HOUR,
+ S5M_ALARM0_WEEKDAY,
+ S5M_ALARM0_DATE,
+ S5M_ALARM0_MONTH,
+ S5M_ALARM0_YEAR1,
+ S5M_ALARM0_YEAR2,
+ S5M_ALARM1_SEC,
+ S5M_ALARM1_MIN,
+ S5M_ALARM1_HOUR,
+ S5M_ALARM1_WEEKDAY,
+ S5M_ALARM1_DATE,
+ S5M_ALARM1_MONTH,
+ S5M_ALARM1_YEAR1,
+ S5M_ALARM1_YEAR2,
+ S5M_ALARM0_CONF,
+ S5M_ALARM1_CONF,
+ S5M_RTC_STATUS,
+ S5M_WTSR_SMPL_CNTL,
+ S5M_RTC_UDR_CON,
+};
+
+#define RTC_I2C_ADDR (0x0C >> 1)
+
+#define HOUR_12 (1 << 7)
+#define HOUR_AMPM (1 << 6)
+#define HOUR_PM (1 << 5)
+#define ALARM0_STATUS (1 << 1)
+#define ALARM1_STATUS (1 << 2)
+#define UPDATE_AD (1 << 0)
+
+enum {
+ RTC_SEC = 0,
+ RTC_MIN,
+ RTC_HOUR,
+ RTC_WEEKDAY,
+ RTC_DATE,
+ RTC_MONTH,
+ RTC_YEAR1,
+ RTC_YEAR2,
+};
+
+#endif /* __LINUX_MFD_S5M_RTC_H */
--
1.7.1
^ permalink raw reply related
* [PATCH 2/3] mfd: Add s5m series irq support
From: Sangbeom Kim @ 2011-10-21 10:28 UTC (permalink / raw)
To: sameo; +Cc: linux-kernel, broonie, Sangbeom Kim
In-Reply-To: <1319192894-19292-1-git-send-email-sbkim73@samsung.com>
This patch support irq for s5m series.
Basically, S5M8767 and S5M8763 irq can be handled by this patch.
Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
---
drivers/mfd/s5m-irq.c | 486 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 486 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/s5m-irq.c
diff --git a/drivers/mfd/s5m-irq.c b/drivers/mfd/s5m-irq.c
new file mode 100644
index 0000000..6a4a71a
--- /dev/null
+++ b/drivers/mfd/s5m-irq.c
@@ -0,0 +1,486 @@
+/*
+ * s5m-irq.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/s5m87xx/s5m-core.h>
+
+struct s5m_irq_data {
+ int reg;
+ int mask;
+};
+
+static struct s5m_irq_data s5m8767_irqs[] = {
+ [S5M8767_IRQ_PWRR] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_PWRR_MASK,
+ },
+ [S5M8767_IRQ_PWRF] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_PWRF_MASK,
+ },
+ [S5M8767_IRQ_PWR1S] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_PWR1S_MASK,
+ },
+ [S5M8767_IRQ_JIGR] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_JIGR_MASK,
+ },
+ [S5M8767_IRQ_JIGF] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_JIGF_MASK,
+ },
+ [S5M8767_IRQ_LOWBAT2] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_LOWBAT2_MASK,
+ },
+ [S5M8767_IRQ_LOWBAT1] = {
+ .reg = 2,
+ .mask = S5M8767_IRQ_LOWBAT1_MASK,
+ },
+ [S5M8767_IRQ_MRB] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_MRB_MASK,
+ },
+ [S5M8767_IRQ_DVSOK2] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_DVSOK2_MASK,
+ },
+ [S5M8767_IRQ_DVSOK3] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_DVSOK3_MASK,
+ },
+ [S5M8767_IRQ_DVSOK4] = {
+ .reg = 3,
+ .mask = S5M8767_IRQ_DVSOK4_MASK,
+ },
+ [S5M8767_IRQ_RTC60S] = {
+ .reg = 4,
+ .mask = S5M8767_IRQ_RTC60S_MASK,
+ },
+ [S5M8767_IRQ_RTCA1] = {
+ .reg = 4,
+ .mask = S5M8767_IRQ_RTCA1_MASK,
+ },
+ [S5M8767_IRQ_RTCA2] = {
+ .reg = 4,
+ .mask = S5M8767_IRQ_RTCA2_MASK,
+ },
+ [S5M8767_IRQ_SMPL] = {
+ .reg = 4,
+ .mask = S5M8767_IRQ_SMPL_MASK,
+ },
+ [S5M8767_IRQ_RTC1S] = {
+ .reg = 4,
+ .mask = S5M8767_IRQ_RTC1S_MASK,
+ },
+ [S5M8767_IRQ_WTSR] = {
+ .reg = 4,
+ .mask = S5M8767_IRQ_WTSR_MASK,
+ },
+};
+
+static struct s5m_irq_data s5m8763_irqs[] = {
+ [S5M8763_IRQ_VDCINF] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_VDCINF_MASK,
+ },
+ [S5M8763_IRQ_VDCINR] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_VDCINR_MASK,
+ },
+ [S5M8763_IRQ_JIGF] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_JIGF_MASK,
+ },
+ [S5M8763_IRQ_JIGR] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_JIGR_MASK,
+ },
+ [S5M8763_IRQ_PWRONF] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_PWRONF_MASK,
+ },
+ [S5M8763_IRQ_PWRONR] = {
+ .reg = 1,
+ .mask = S5M8763_IRQ_PWRONR_MASK,
+ },
+ [S5M8763_IRQ_WTSREVNT] = {
+ .reg = 2,
+ .mask = S5M8763_IRQ_WTSREVNT_MASK,
+ },
+ [S5M8763_IRQ_SMPLEVNT] = {
+ .reg = 2,
+ .mask = S5M8763_IRQ_SMPLEVNT_MASK,
+ },
+ [S5M8763_IRQ_ALARM1] = {
+ .reg = 2,
+ .mask = S5M8763_IRQ_ALARM1_MASK,
+ },
+ [S5M8763_IRQ_ALARM0] = {
+ .reg = 2,
+ .mask = S5M8763_IRQ_ALARM0_MASK,
+ },
+ [S5M8763_IRQ_ONKEY1S] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_ONKEY1S_MASK,
+ },
+ [S5M8763_IRQ_TOPOFFR] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_TOPOFFR_MASK,
+ },
+ [S5M8763_IRQ_VDCINOVPR] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_VDCINOVPR_MASK,
+ },
+ [S5M8763_IRQ_CHGRSTF] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_CHGRSTF_MASK,
+ },
+ [S5M8763_IRQ_DONER] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_DONER_MASK,
+ },
+ [S5M8763_IRQ_CHGFAULT] = {
+ .reg = 3,
+ .mask = S5M8763_IRQ_CHGFAULT_MASK,
+ },
+ [S5M8763_IRQ_LOBAT1] = {
+ .reg = 4,
+ .mask = S5M8763_IRQ_LOBAT1_MASK,
+ },
+ [S5M8763_IRQ_LOBAT2] = {
+ .reg = 4,
+ .mask = S5M8763_IRQ_LOBAT2_MASK,
+ },
+};
+
+static inline struct s5m_irq_data *
+irq_to_s5m8767_irq(struct s5m87xx_dev *s5m87xx, int irq)
+{
+ return &s5m8767_irqs[irq - s5m87xx->irq_base];
+}
+
+static void s5m8767_irq_lock(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&s5m87xx->irqlock);
+}
+
+static void s5m8767_irq_sync_unlock(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) {
+ if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) {
+ s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i];
+ s5m_reg_write(s5m87xx, S5M8767_REG_INT1M + i,
+ s5m87xx->irq_masks_cur[i]);
+ }
+ }
+
+ mutex_unlock(&s5m87xx->irqlock);
+}
+
+static void s5m8767_irq_unmask(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx,
+ data->irq);
+
+ s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
+}
+
+static void s5m8767_irq_mask(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx,
+ data->irq);
+
+ s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
+}
+
+static struct irq_chip s5m8767_irq_chip = {
+ .name = "s5m8767",
+ .irq_bus_lock = s5m8767_irq_lock,
+ .irq_bus_sync_unlock = s5m8767_irq_sync_unlock,
+ .irq_mask = s5m8767_irq_mask,
+ .irq_unmask = s5m8767_irq_unmask,
+};
+
+static inline struct s5m_irq_data *
+irq_to_s5m8763_irq(struct s5m87xx_dev *s5m87xx, int irq)
+{
+ return &s5m8763_irqs[irq - s5m87xx->irq_base];
+}
+
+static void s5m8763_irq_lock(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+
+ mutex_lock(&s5m87xx->irqlock);
+}
+
+static void s5m8763_irq_sync_unlock(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) {
+ if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) {
+ s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i];
+ s5m_reg_write(s5m87xx, S5M8763_REG_IRQM1 + i,
+ s5m87xx->irq_masks_cur[i]);
+ }
+ }
+
+ mutex_unlock(&s5m87xx->irqlock);
+}
+
+static void s5m8763_irq_unmask(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx,
+ data->irq);
+
+ s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
+}
+
+static void s5m8763_irq_mask(struct irq_data *data)
+{
+ struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
+ struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx,
+ data->irq);
+
+ s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
+}
+
+static struct irq_chip s5m8763_irq_chip = {
+ .name = "s5m8763",
+ .irq_bus_lock = s5m8763_irq_lock,
+ .irq_bus_sync_unlock = s5m8763_irq_sync_unlock,
+ .irq_mask = s5m8763_irq_mask,
+ .irq_unmask = s5m8763_irq_unmask,
+};
+
+static irqreturn_t s5m8767_irq_thread(int irq, void *data)
+{
+ struct s5m87xx_dev *s5m87xx = data;
+ u8 irq_reg[NUM_IRQ_REGS-1];
+ int ret;
+ int i;
+
+ ret = s5m_bulk_read(s5m87xx, S5M8767_REG_INT1,
+ NUM_IRQ_REGS - 1, irq_reg);
+ if (ret < 0) {
+ dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ for (i = 0; i < NUM_IRQ_REGS - 1; i++)
+ irq_reg[i] &= ~s5m87xx->irq_masks_cur[i];
+
+ for (i = 0; i < S5M8767_IRQ_NR; i++) {
+ if (irq_reg[s5m8767_irqs[i].reg - 1] & s5m8767_irqs[i].mask)
+ handle_nested_irq(s5m87xx->irq_base + i);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t s5m8763_irq_thread(int irq, void *data)
+{
+ struct s5m87xx_dev *s5m87xx = data;
+ u8 irq_reg[NUM_IRQ_REGS];
+ int ret;
+ int i;
+
+ ret = s5m_bulk_read(s5m87xx, S5M8763_REG_IRQ1,
+ NUM_IRQ_REGS, irq_reg);
+ if (ret < 0) {
+ dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ for (i = 0; i < NUM_IRQ_REGS; i++)
+ irq_reg[i] &= ~s5m87xx->irq_masks_cur[i];
+
+ for (i = 0; i < S5M8763_IRQ_NR; i++) {
+ if (irq_reg[s5m8763_irqs[i].reg - 1] & s5m8763_irqs[i].mask)
+ handle_nested_irq(s5m87xx->irq_base + i);
+ }
+
+ return IRQ_HANDLED;
+}
+
+int s5m_irq_resume(struct s5m87xx_dev *s5m87xx)
+{
+ if (s5m87xx->irq && s5m87xx->irq_base){
+ switch (s5m87xx->device_type) {
+ case S5M8763X:
+ s5m8763_irq_thread(s5m87xx->irq_base, s5m87xx);
+ break;
+ case S5M8767X:
+ s5m8767_irq_thread(s5m87xx->irq_base, s5m87xx);
+ break;
+ default:
+ break;
+
+ }
+ }
+ return 0;
+}
+
+int s5m_irq_init(struct s5m87xx_dev *s5m87xx)
+{
+ int i;
+ int cur_irq;
+ int ret = 0;
+ int type = s5m87xx->device_type;
+
+ if (!s5m87xx->irq) {
+ dev_warn(s5m87xx->dev,
+ "No interrupt specified, no interrupts\n");
+ s5m87xx->irq_base = 0;
+ return 0;
+ }
+
+ if (!s5m87xx->irq_base) {
+ dev_err(s5m87xx->dev,
+ "No interrupt base specified, no interrupts\n");
+ return 0;
+ }
+
+ mutex_init(&s5m87xx->irqlock);
+
+ switch (type) {
+ case S5M8763X:
+ for (i = 0; i < NUM_IRQ_REGS; i++) {
+ s5m87xx->irq_masks_cur[i] = 0xff;
+ s5m87xx->irq_masks_cache[i] = 0xff;
+ s5m_reg_write(s5m87xx, S5M8763_REG_IRQM1 + i,
+ 0xff);
+ }
+
+ s5m_reg_write(s5m87xx, S5M8763_REG_STATUSM1, 0xff);
+ s5m_reg_write(s5m87xx, S5M8763_REG_STATUSM2, 0xff);
+
+ for (i = 0; i < S5M8763_IRQ_NR; i++) {
+ cur_irq = i + s5m87xx->irq_base;
+ irq_set_chip_data(cur_irq, s5m87xx);
+ irq_set_chip_and_handler(cur_irq, &s5m8763_irq_chip,
+ handle_edge_irq);
+ irq_set_nested_thread(cur_irq, 1);
+#ifdef CONFIG_ARM
+ set_irq_flags(cur_irq, IRQF_VALID);
+#else
+ irq_set_noprobe(cur_irq);
+#endif
+ }
+
+ ret = request_threaded_irq(s5m87xx->irq, NULL,
+ s5m8763_irq_thread,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "s5m87xx-irq", s5m87xx);
+ if (ret) {
+ dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
+ s5m87xx->irq, ret);
+ return ret;
+ }
+ break;
+ case S5M8767X:
+ for (i = 0; i < NUM_IRQ_REGS - 1; i++) {
+ s5m87xx->irq_masks_cur[i] = 0xff;
+ s5m87xx->irq_masks_cache[i] = 0xff;
+ s5m_reg_write(s5m87xx, S5M8767_REG_INT1M + i,
+ 0xff);
+ }
+
+ for (i = 0; i < S5M8767_IRQ_NR; i++) {
+ cur_irq = i + s5m87xx->irq_base;
+ irq_set_chip_data(cur_irq, s5m87xx);
+ if (ret) {
+ dev_err(s5m87xx->dev,
+ "Failed to irq_set_chip_data %d: %d\n",
+ s5m87xx->irq, ret);
+ return ret;
+ }
+
+ irq_set_chip_and_handler(cur_irq, &s5m8767_irq_chip,
+ handle_edge_irq);
+ irq_set_nested_thread(cur_irq, 1);
+#ifdef CONFIG_ARM
+ set_irq_flags(cur_irq, IRQF_VALID);
+#else
+ irq_set_noprobe(cur_irq);
+#endif
+ }
+
+ ret = request_threaded_irq(s5m87xx->irq, NULL,
+ s5m8767_irq_thread,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "s5m87xx-irq", s5m87xx);
+ if (ret) {
+ dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
+ s5m87xx->irq, ret);
+ return ret;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!s5m87xx->ono)
+ return 0;
+
+ switch (type) {
+ case S5M8763X:
+ ret = request_threaded_irq(s5m87xx->ono, NULL,
+ s5m8763_irq_thread,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT, "s5m87xx-ono",
+ s5m87xx);
+ break;
+ case S5M8767X:
+ ret = request_threaded_irq(s5m87xx->ono, NULL,
+ s5m8767_irq_thread,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT, "s5m87xx-ono", s5m87xx);
+ break;
+ default:
+ break;
+ }
+
+ if (ret)
+ dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
+ s5m87xx->ono, ret);
+
+ return 0;
+}
+
+void s5m_irq_exit(struct s5m87xx_dev *s5m87xx)
+{
+ if (s5m87xx->ono)
+ free_irq(s5m87xx->ono, s5m87xx);
+
+ if (s5m87xx->irq)
+ free_irq(s5m87xx->irq, s5m87xx);
+}
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 13/X] uprobes: introduce UTASK_SSTEP_TRAPPED logic
From: Ananth N Mavinakayanahalli @ 2011-10-24 15:16 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Srikar Dronamraju, Peter Zijlstra, Ingo Molnar, Steven Rostedt,
Linux-mm, Arnaldo Carvalho de Melo, Linus Torvalds,
Jonathan Corbet, Masami Hiramatsu, Hugh Dickins,
Christoph Hellwig, Thomas Gleixner, Andi Kleen, Andrew Morton,
Jim Keniston, Roland McGrath, LKML
In-Reply-To: <20111024144127.GA14975@redhat.com>
On Mon, Oct 24, 2011 at 04:41:27PM +0200, Oleg Nesterov wrote:
> On 10/22, Ananth N Mavinakayanahalli wrote:
> >
> > On Wed, Oct 19, 2011 at 11:53:44PM +0200, Oleg Nesterov wrote:
> > > Finally, add UTASK_SSTEP_TRAPPED state/code to handle the case when
> > > xol insn itself triggers the signal.
> > >
> > > In this case we should restart the original insn even if the task is
> > > already SIGKILL'ed (say, the coredump should report the correct ip).
> > > This is even more important if the task has a handler for SIGSEGV/etc,
> > > The _same_ instruction should be repeated again after return from the
> > > signal handler, and SSTEP can never finish in this case.
> >
> > Oleg,
> >
> > Not sure I understand this completely...
>
> I hope you do not think I do ;)
I think you understand it better than you think you do :-)
> > When you say 'correct ip' you mean the original vaddr where we now have
> > a uprobe breakpoint and not the xol copy, right?
>
> Yes,
>
> > Coredump needs to report the correct ip, but should it also not report
> > correctly the instruction that caused the signal? Ergo, shouldn't we
> > put the original instruction back at the uprobed vaddr?
>
> OK, now I see what you mean. I was confused by the "restore the original
> instruction before _restart_" suggestion.
>
> Agreed! it would be nice to "hide" these int3's if we dump the core, but
> I think this is a bit off-topic. It makes sense to do this in any case,
> even if the core-dumping was triggered by another thread/insn. It makes
> sense to remove all int3's, not only at regs->ip location. But how can
> we do this? This is nontrivial.
I don't think that is a problem.. see below...
> And. Even worse. Suppose that you do "gdb probed_application". Now you
> see int3's in the disassemble output. What can we do?
In this case, nothing.
> I think we can do nothing, at least currently. This just reflects the
> fact that uprobe connects to inode, not to process/mm/etc.
>
> What do you think?
Thinking further on this, in the normal 'running gdb on a core' case, we
won't have this problem, as the binary that we point gdb to, will be a
pristine one, without the uprobe int3s, right?
Ananth
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.