* [PATCH 0/3] Malta/SEAD3 kernel image size patches for 3.18 @ 2014-10-09 9:34 ` Markos Chandras 0 siblings, 0 replies; 20+ messages in thread From: Markos Chandras @ 2014-10-09 9:34 UTC (permalink / raw) To: linux-mips; +Cc: Markos Chandras Hi, A few patches to reduce the size of the kernel image for Malta and SEAD3 by improving the dependencies on certain source files. A different approach for i2c and led patches has been posted before: http://patchwork.linux-mips.org/patch/5802/ Even though none of the original requests have been addressed, I still feel these patches do not make things any worse. Hopefully not too late for 3.18 Markos Chandras (3): MIPS: Malta: Do not build the malta-amon.c file if CMP is not enabled MIPS: sead3: Build the I2C related devices if CONFIG_I2C is enabled MIPS: sead3: Only build the led driver is LEDS_CLASS is enabled arch/mips/mti-malta/Makefile | 3 ++- arch/mips/mti-sead3/Makefile | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) -- 2.1.2 ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 0/3] Malta/SEAD3 kernel image size patches for 3.18 @ 2014-10-09 9:34 ` Markos Chandras 0 siblings, 0 replies; 20+ messages in thread From: Markos Chandras @ 2014-10-09 9:34 UTC (permalink / raw) To: linux-mips; +Cc: Markos Chandras Hi, A few patches to reduce the size of the kernel image for Malta and SEAD3 by improving the dependencies on certain source files. A different approach for i2c and led patches has been posted before: http://patchwork.linux-mips.org/patch/5802/ Even though none of the original requests have been addressed, I still feel these patches do not make things any worse. Hopefully not too late for 3.18 Markos Chandras (3): MIPS: Malta: Do not build the malta-amon.c file if CMP is not enabled MIPS: sead3: Build the I2C related devices if CONFIG_I2C is enabled MIPS: sead3: Only build the led driver is LEDS_CLASS is enabled arch/mips/mti-malta/Makefile | 3 ++- arch/mips/mti-sead3/Makefile | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) -- 2.1.2 ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 1/3] MIPS: Malta: Do not build the malta-amon.c file if CMP is not enabled @ 2014-10-09 9:34 ` Markos Chandras 0 siblings, 0 replies; 20+ messages in thread From: Markos Chandras @ 2014-10-09 9:34 UTC (permalink / raw) To: linux-mips; +Cc: Markos Chandras The malta-amon.c file provides functions to access the YAMON Monitoring interface to bring up secondary VPEs in case of SMP/CMP. As a result of which, there is no need to build it if CMP is not used. Reviewed-by: Paul Burton <paul.burton@imgtec.com> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> --- arch/mips/mti-malta/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index b9510ea8db56..6510ace272d4 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -5,8 +5,9 @@ # Copyright (C) 2008 Wind River Systems, Inc. # written by Ralf Baechle <ralf@linux-mips.org> # -obj-y := malta-amon.o malta-display.o malta-init.o \ +obj-y := malta-display.o malta-init.o \ malta-int.o malta-memory.o malta-platform.o \ malta-reset.o malta-setup.o malta-time.o +obj-$(CONFIG_MIPS_CMP) += malta-amon.o obj-$(CONFIG_MIPS_MALTA_PM) += malta-pm.o -- 2.1.2 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 1/3] MIPS: Malta: Do not build the malta-amon.c file if CMP is not enabled @ 2014-10-09 9:34 ` Markos Chandras 0 siblings, 0 replies; 20+ messages in thread From: Markos Chandras @ 2014-10-09 9:34 UTC (permalink / raw) To: linux-mips; +Cc: Markos Chandras The malta-amon.c file provides functions to access the YAMON Monitoring interface to bring up secondary VPEs in case of SMP/CMP. As a result of which, there is no need to build it if CMP is not used. Reviewed-by: Paul Burton <paul.burton@imgtec.com> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> --- arch/mips/mti-malta/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index b9510ea8db56..6510ace272d4 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -5,8 +5,9 @@ # Copyright (C) 2008 Wind River Systems, Inc. # written by Ralf Baechle <ralf@linux-mips.org> # -obj-y := malta-amon.o malta-display.o malta-init.o \ +obj-y := malta-display.o malta-init.o \ malta-int.o malta-memory.o malta-platform.o \ malta-reset.o malta-setup.o malta-time.o +obj-$(CONFIG_MIPS_CMP) += malta-amon.o obj-$(CONFIG_MIPS_MALTA_PM) += malta-pm.o -- 2.1.2 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 2/3] MIPS: sead3: Build the I2C related devices if CONFIG_I2C is enabled @ 2014-10-09 9:34 ` Markos Chandras 0 siblings, 0 replies; 20+ messages in thread From: Markos Chandras @ 2014-10-09 9:34 UTC (permalink / raw) To: linux-mips; +Cc: Markos Chandras There is no point building the drivers for the i2c related devices if CONFIG_I2C is not enabled. This also fixes a randconfig problem: arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_probe': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:345:2: error: implicit declaration of function 'i2c_add_numbered_adapter' [-Werror=implicit-function-declaration] ret = i2c_add_numbered_adapter(&priv->adap); ^ arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_remove': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:361:2: error: implicit declaration of function 'i2c_del_adapter' [-Werror=implicit-function-declaration] i2c_del_adapter(&priv->adap); Reviewed-by: Steven J. Hill <Steven.Hill@imgtec.com> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> --- arch/mips/mti-sead3/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index 071786fa234b..a632b9cfe526 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -13,11 +13,11 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ sead3-platform.o sead3-reset.o \ sead3-setup.o sead3-time.o -obj-y += sead3-i2c-dev.o sead3-i2c.o \ - sead3-pic32-i2c-drv.o sead3-pic32-bus.o \ - leds-sead3.o sead3-leds.o +obj-y += leds-sead3.o sead3-leds.o obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o +obj-$(CONFIG_I2C) += sead3-i2c.o sead3-i2c-dev.o \ + sead3-pic32-bus.o lsead3-pic32-i2c-drv.o obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o obj-$(CONFIG_OF) += sead3.dtb.o -- 2.1.2 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 2/3] MIPS: sead3: Build the I2C related devices if CONFIG_I2C is enabled @ 2014-10-09 9:34 ` Markos Chandras 0 siblings, 0 replies; 20+ messages in thread From: Markos Chandras @ 2014-10-09 9:34 UTC (permalink / raw) To: linux-mips; +Cc: Markos Chandras There is no point building the drivers for the i2c related devices if CONFIG_I2C is not enabled. This also fixes a randconfig problem: arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_probe': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:345:2: error: implicit declaration of function 'i2c_add_numbered_adapter' [-Werror=implicit-function-declaration] ret = i2c_add_numbered_adapter(&priv->adap); ^ arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_remove': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:361:2: error: implicit declaration of function 'i2c_del_adapter' [-Werror=implicit-function-declaration] i2c_del_adapter(&priv->adap); Reviewed-by: Steven J. Hill <Steven.Hill@imgtec.com> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> --- arch/mips/mti-sead3/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index 071786fa234b..a632b9cfe526 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -13,11 +13,11 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ sead3-platform.o sead3-reset.o \ sead3-setup.o sead3-time.o -obj-y += sead3-i2c-dev.o sead3-i2c.o \ - sead3-pic32-i2c-drv.o sead3-pic32-bus.o \ - leds-sead3.o sead3-leds.o +obj-y += leds-sead3.o sead3-leds.o obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o +obj-$(CONFIG_I2C) += sead3-i2c.o sead3-i2c-dev.o \ + sead3-pic32-bus.o lsead3-pic32-i2c-drv.o obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o obj-$(CONFIG_OF) += sead3.dtb.o -- 2.1.2 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 2/3] MIPS: sead3: Build the I2C related devices if CONFIG_I2C is enabled 2014-10-09 9:34 ` Markos Chandras (?) @ 2014-10-23 18:19 ` Ralf Baechle 2014-10-24 8:15 ` Ralf Baechle [not found] ` <20141023181925.GA6719-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org> -1 siblings, 2 replies; 20+ messages in thread From: Ralf Baechle @ 2014-10-23 18:19 UTC (permalink / raw) To: Markos Chandras; +Cc: linux-mips On Thu, Oct 09, 2014 at 10:34:20AM +0100, Markos Chandras wrote: > There is no point building the drivers for the i2c related devices if > CONFIG_I2C is not enabled. > > This also fixes a randconfig problem: > > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_probe': > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:345:2: error: implicit declaration of > function 'i2c_add_numbered_adapter' [-Werror=implicit-function-declaration] > ret = i2c_add_numbered_adapter(&priv->adap); > ^ > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function > 'i2c_platform_remove': > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:361:2: error: implicit declaration > of function 'i2c_del_adapter' [-Werror=implicit-function-declaration] > i2c_del_adapter(&priv->adap); The platform devices should always be registered. And why on earth is there an I2C drivers in arch? That should rather go to drivers/i2c/busses/. Ralf ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/3] MIPS: sead3: Build the I2C related devices if CONFIG_I2C is enabled 2014-10-23 18:19 ` Ralf Baechle @ 2014-10-24 8:15 ` Ralf Baechle 2014-10-24 10:06 ` [PATCH] MIPS: SEAD3: Nuke unused sead3-pic32-i2c-drv Ralf Baechle [not found] ` <20141023181925.GA6719-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org> 1 sibling, 1 reply; 20+ messages in thread From: Ralf Baechle @ 2014-10-24 8:15 UTC (permalink / raw) To: Markos Chandras, Chris Dearman; +Cc: linux-mips On Thu, Oct 23, 2014 at 08:19:26PM +0200, Ralf Baechle wrote: > > There is no point building the drivers for the i2c related devices if > > CONFIG_I2C is not enabled. > > > > This also fixes a randconfig problem: > > > > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_probe': > > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:345:2: error: implicit declaration of > > function 'i2c_add_numbered_adapter' [-Werror=implicit-function-declaration] > > ret = i2c_add_numbered_adapter(&priv->adap); > > ^ > > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function > > 'i2c_platform_remove': > > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:361:2: error: implicit declaration > > of function 'i2c_del_adapter' [-Werror=implicit-function-declaration] > > i2c_del_adapter(&priv->adap); > > The platform devices should always be registered. > > And why on earth is there an I2C drivers in arch? That should rather > go to drivers/i2c/busses/. It's even worse. arch/mips/mti-sead3/sead3-pic32-i2c-drv.c registers a driver - but nothing registers a platform device for it. And nobody's apparently missing a functioning driver. Nuke? Ralf ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH] MIPS: SEAD3: Nuke unused sead3-pic32-i2c-drv. 2014-10-24 8:15 ` Ralf Baechle @ 2014-10-24 10:06 ` Ralf Baechle 0 siblings, 0 replies; 20+ messages in thread From: Ralf Baechle @ 2014-10-24 10:06 UTC (permalink / raw) To: Markos Chandras, Chris Dearman; +Cc: linux-mips A platform driver for which nothing ever registers the corresponding platform device. This also fixes a randconfig problem: arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_probe': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:345:2: error: implicit declaration of function 'i2c_add_numbered_adapter' [-Werror=implicit-function-declaration] ret = i2c_add_numbered_adapter(&priv->adap); ^ arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_remove': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:361:2: error: implicit declaration of function 'i2c_del_adapter' [-Werror=implicit-function-declaration] i2c_del_adapter(&priv->adap); Signed-off-by: Ralf Baechle <ralf@linux-mips.org> diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index febf433..9d9ff6f 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -14,8 +14,7 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ sead3-setup.o sead3-time.o obj-y += sead3-i2c-dev.o sead3-i2c.o \ - sead3-pic32-i2c-drv.o sead3-pic32-bus.o \ - leds-sead3.o sead3-leds.o + sead3-pic32-bus.o leds-sead3.o sead3-leds.o obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o diff --git a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c deleted file mode 100644 index 80fe194..0000000 --- a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/delay.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/i2c.h> -#include <linux/slab.h> - -#define PIC32_I2CxCON 0x0000 -#define PIC32_I2CxCONCLR 0x0004 -#define PIC32_I2CxCONSET 0x0008 -#define PIC32_I2CxCONINV 0x000C -#define I2CCON_ON (1<<15) -#define I2CCON_FRZ (1<<14) -#define I2CCON_SIDL (1<<13) -#define I2CCON_SCLREL (1<<12) -#define I2CCON_STRICT (1<<11) -#define I2CCON_A10M (1<<10) -#define I2CCON_DISSLW (1<<9) -#define I2CCON_SMEN (1<<8) -#define I2CCON_GCEN (1<<7) -#define I2CCON_STREN (1<<6) -#define I2CCON_ACKDT (1<<5) -#define I2CCON_ACKEN (1<<4) -#define I2CCON_RCEN (1<<3) -#define I2CCON_PEN (1<<2) -#define I2CCON_RSEN (1<<1) -#define I2CCON_SEN (1<<0) - -#define PIC32_I2CxSTAT 0x0010 -#define PIC32_I2CxSTATCLR 0x0014 -#define PIC32_I2CxSTATSET 0x0018 -#define PIC32_I2CxSTATINV 0x001C -#define I2CSTAT_ACKSTAT (1<<15) -#define I2CSTAT_TRSTAT (1<<14) -#define I2CSTAT_BCL (1<<10) -#define I2CSTAT_GCSTAT (1<<9) -#define I2CSTAT_ADD10 (1<<8) -#define I2CSTAT_IWCOL (1<<7) -#define I2CSTAT_I2COV (1<<6) -#define I2CSTAT_DA (1<<5) -#define I2CSTAT_P (1<<4) -#define I2CSTAT_S (1<<3) -#define I2CSTAT_RW (1<<2) -#define I2CSTAT_RBF (1<<1) -#define I2CSTAT_TBF (1<<0) - -#define PIC32_I2CxADD 0x0020 -#define PIC32_I2CxADDCLR 0x0024 -#define PIC32_I2CxADDSET 0x0028 -#define PIC32_I2CxADDINV 0x002C -#define PIC32_I2CxMSK 0x0030 -#define PIC32_I2CxMSKCLR 0x0034 -#define PIC32_I2CxMSKSET 0x0038 -#define PIC32_I2CxMSKINV 0x003C -#define PIC32_I2CxBRG 0x0040 -#define PIC32_I2CxBRGCLR 0x0044 -#define PIC32_I2CxBRGSET 0x0048 -#define PIC32_I2CxBRGINV 0x004C -#define PIC32_I2CxTRN 0x0050 -#define PIC32_I2CxTRNCLR 0x0054 -#define PIC32_I2CxTRNSET 0x0058 -#define PIC32_I2CxTRNINV 0x005C -#define PIC32_I2CxRCV 0x0060 - -struct i2c_platform_data { - u32 base; - struct i2c_adapter adap; - u32 xfer_timeout; - u32 ack_timeout; - u32 ctl_timeout; -}; - -extern u32 pic32_bus_readl(u32 reg); -extern void pic32_bus_writel(u32 val, u32 reg); - -static inline void -StartI2C(struct i2c_platform_data *adap) -{ - pr_debug("StartI2C\n"); - pic32_bus_writel(I2CCON_SEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void -StopI2C(struct i2c_platform_data *adap) -{ - pr_debug("StopI2C\n"); - pic32_bus_writel(I2CCON_PEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void -AckI2C(struct i2c_platform_data *adap) -{ - pr_debug("AckI2C\n"); - pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); - pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void -NotAckI2C(struct i2c_platform_data *adap) -{ - pr_debug("NakI2C\n"); - pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); - pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); -} - -static inline int -IdleI2C(struct i2c_platform_data *adap) -{ - int i; - - pr_debug("IdleI2C\n"); - for (i = 0; i < adap->ctl_timeout; i++) { - if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & - (I2CCON_ACKEN | I2CCON_RCEN | I2CCON_PEN | I2CCON_RSEN | - I2CCON_SEN)) == 0) && - ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - (I2CSTAT_TRSTAT)) == 0)) - return 0; - udelay(1); - } - return -ETIMEDOUT; -} - -static inline u32 -MasterWriteI2C(struct i2c_platform_data *adap, u32 byte) -{ - pr_debug("MasterWriteI2C\n"); - - pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); - - return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_IWCOL; -} - -static inline u32 -MasterReadI2C(struct i2c_platform_data *adap) -{ - pr_debug("MasterReadI2C\n"); - - pic32_bus_writel(I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); - - while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & I2CCON_RCEN) - ; - - pic32_bus_writel(I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); - - return pic32_bus_readl(adap->base + PIC32_I2CxRCV); -} - -static int -do_address(struct i2c_platform_data *adap, unsigned int addr, int rd) -{ - pr_debug("doaddress\n"); - - IdleI2C(adap); - StartI2C(adap); - IdleI2C(adap); - - addr <<= 1; - if (rd) - addr |= 1; - - if (MasterWriteI2C(adap, addr)) - return -EIO; - IdleI2C(adap); - if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_ACKSTAT) - return -EIO; - return 0; -} - -static int -i2c_read(struct i2c_platform_data *adap, unsigned char *buf, - unsigned int len) -{ - int i; - u32 data; - - pr_debug("i2c_read\n"); - - i = 0; - while (i < len) { - data = MasterReadI2C(adap); - buf[i++] = data; - if (i < len) - AckI2C(adap); - else - NotAckI2C(adap); - } - - StopI2C(adap); - IdleI2C(adap); - return 0; -} - -static int -i2c_write(struct i2c_platform_data *adap, unsigned char *buf, - unsigned int len) -{ - int i; - u32 data; - - pr_debug("i2c_write\n"); - - i = 0; - while (i < len) { - data = buf[i]; - if (MasterWriteI2C(adap, data)) - return -EIO; - IdleI2C(adap); - if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - I2CSTAT_ACKSTAT) - return -EIO; - i++; - } - - StopI2C(adap); - IdleI2C(adap); - return 0; -} - -static int -platform_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) -{ - struct i2c_platform_data *adap = i2c_adap->algo_data; - struct i2c_msg *p; - int i, err = 0; - - pr_debug("platform_xfer\n"); - for (i = 0; i < num; i++) { -#define __BUFSIZE 80 - int ii; - static char buf[__BUFSIZE]; - char *b = buf; - - p = &msgs[i]; - b += sprintf(buf, " [%d bytes]", p->len); - if ((p->flags & I2C_M_RD) == 0) { - for (ii = 0; ii < p->len; ii++) { - if (b < &buf[__BUFSIZE-4]) { - b += sprintf(b, " %02x", p->buf[ii]); - } else { - strcat(b, "..."); - break; - } - } - } - pr_debug("xfer%d: DevAddr: %04x Op:%s Data:%s\n", i, p->addr, - (p->flags & I2C_M_RD) ? "Rd" : "Wr", buf); - } - - - for (i = 0; !err && i < num; i++) { - p = &msgs[i]; - err = do_address(adap, p->addr, p->flags & I2C_M_RD); - if (err || !p->len) - continue; - if (p->flags & I2C_M_RD) - err = i2c_read(adap, p->buf, p->len); - else - err = i2c_write(adap, p->buf, p->len); - } - - /* Return the number of messages processed, or the error code. */ - if (err == 0) - err = num; - - return err; -} - -static u32 -platform_func(struct i2c_adapter *adap) -{ - pr_debug("platform_algo\n"); - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm platform_algo = { - .master_xfer = platform_xfer, - .functionality = platform_func, -}; - -static void i2c_platform_setup(struct i2c_platform_data *priv) -{ - pr_debug("i2c_platform_setup\n"); - - pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); - pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONCLR); - pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONSET); - pic32_bus_writel((I2CSTAT_BCL | I2CSTAT_IWCOL), - (priv->base + PIC32_I2CxSTATCLR)); -} - -static void i2c_platform_disable(struct i2c_platform_data *priv) -{ - pr_debug("i2c_platform_disable\n"); -} - -static int i2c_platform_probe(struct platform_device *pdev) -{ - struct i2c_platform_data *priv; - struct resource *r; - int ret; - - pr_debug("i2c_platform_probe\n"); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) - return -ENODEV; - - priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_platform_data), - GFP_KERNEL); - if (!priv) - return -ENOMEM; - - /* FIXME: need to allocate resource in PIC32 space */ -#if 0 - priv->base = bus_request_region(r->start, resource_size(r), - pdev->name); -#else - priv->base = r->start; -#endif - if (!priv->base) - return -EBUSY; - - priv->xfer_timeout = 200; - priv->ack_timeout = 200; - priv->ctl_timeout = 200; - - priv->adap.nr = pdev->id; - priv->adap.algo = &platform_algo; - priv->adap.algo_data = priv; - priv->adap.dev.parent = &pdev->dev; - strlcpy(priv->adap.name, "PIC32 I2C", sizeof(priv->adap.name)); - - i2c_platform_setup(priv); - - ret = i2c_add_numbered_adapter(&priv->adap); - if (ret) { - i2c_platform_disable(priv); - return ret; - } - - platform_set_drvdata(pdev, priv); - return 0; -} - -static int i2c_platform_remove(struct platform_device *pdev) -{ - struct i2c_platform_data *priv = platform_get_drvdata(pdev); - - pr_debug("i2c_platform_remove\n"); - platform_set_drvdata(pdev, NULL); - i2c_del_adapter(&priv->adap); - i2c_platform_disable(priv); - return 0; -} - -#ifdef CONFIG_PM -static int -i2c_platform_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct i2c_platform_data *priv = platform_get_drvdata(pdev); - - dev_dbg(&pdev->dev, "i2c_platform_disable\n"); - i2c_platform_disable(priv); - - return 0; -} - -static int -i2c_platform_resume(struct platform_device *pdev) -{ - struct i2c_platform_data *priv = platform_get_drvdata(pdev); - - dev_dbg(&pdev->dev, "i2c_platform_setup\n"); - i2c_platform_setup(priv); - - return 0; -} -#else -#define i2c_platform_suspend NULL -#define i2c_platform_resume NULL -#endif - -static struct platform_driver i2c_platform_driver = { - .driver = { - .name = "i2c_pic32", - .owner = THIS_MODULE, - }, - .probe = i2c_platform_probe, - .remove = i2c_platform_remove, - .suspend = i2c_platform_suspend, - .resume = i2c_platform_resume, -}; - -static int __init -i2c_platform_init(void) -{ - pr_debug("i2c_platform_init\n"); - return platform_driver_register(&i2c_platform_driver); -} - -static void __exit -i2c_platform_exit(void) -{ - pr_debug("i2c_platform_exit\n"); - platform_driver_unregister(&i2c_platform_driver); -} - -MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); -MODULE_DESCRIPTION("PIC32 I2C driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_platform_init); -module_exit(i2c_platform_exit); ^ permalink raw reply related [flat|nested] 20+ messages in thread
[parent not found: <20141023181925.GA6719-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>]
* [PATCH] MIPS/I2C: Move SEAD3 I2C driver to where it belongs. 2014-10-23 18:19 ` Ralf Baechle @ 2014-10-24 12:26 ` Ralf Baechle [not found] ` <20141023181925.GA6719-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org> 1 sibling, 0 replies; 20+ messages in thread From: Ralf Baechle @ 2014-10-24 12:26 UTC (permalink / raw) To: Markos Chandras, Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA, Chris Dearman Fixes the following build problem if CONFIG_I2C is disabled: arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_probe': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:345:2: error: implicit declaration of function 'i2c_add_numbered_adapter' [-Werror=implicit-function-declaration] ret = i2c_add_numbered_adapter(&priv->adap); ^ arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_remove': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:361:2: error: implicit declaration of function 'i2c_del_adapter' [-Werror=implicit-function-declaration] i2c_del_adapter(&priv->adap); Signed-off-by: Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org> Cc: Markos Chandras <markos.chandras-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org> Cc: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org Cc: Chris Dearman <chris.dearman-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org> diff --git a/arch/mips/mti-sead3/sead3-i2c-drv.c b/arch/mips/mti-sead3/sead3-i2c-drv.c deleted file mode 100644 index 1f787a6..0000000 --- a/arch/mips/mti-sead3/sead3-i2c-drv.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> - -#define PIC32_I2CxCON 0x0000 -#define PIC32_I2CCON_ON (1<<15) -#define PIC32_I2CCON_ACKDT (1<<5) -#define PIC32_I2CCON_ACKEN (1<<4) -#define PIC32_I2CCON_RCEN (1<<3) -#define PIC32_I2CCON_PEN (1<<2) -#define PIC32_I2CCON_RSEN (1<<1) -#define PIC32_I2CCON_SEN (1<<0) -#define PIC32_I2CxCONCLR 0x0004 -#define PIC32_I2CxCONSET 0x0008 -#define PIC32_I2CxSTAT 0x0010 -#define PIC32_I2CxSTATCLR 0x0014 -#define PIC32_I2CSTAT_ACKSTAT (1<<15) -#define PIC32_I2CSTAT_TRSTAT (1<<14) -#define PIC32_I2CSTAT_BCL (1<<10) -#define PIC32_I2CSTAT_IWCOL (1<<7) -#define PIC32_I2CSTAT_I2COV (1<<6) -#define PIC32_I2CxBRG 0x0040 -#define PIC32_I2CxTRN 0x0050 -#define PIC32_I2CxRCV 0x0060 - -static DEFINE_SPINLOCK(pic32_bus_lock); - -static void __iomem *bus_xfer = (void __iomem *)0xbf000600; -static void __iomem *bus_status = (void __iomem *)0xbf000060; - -#define DELAY() udelay(100) - -static inline unsigned int ioready(void) -{ - return readl(bus_status) & 1; -} - -static inline void wait_ioready(void) -{ - do { } while (!ioready()); -} - -static inline void wait_ioclear(void) -{ - do { } while (ioready()); -} - -static inline void check_ioclear(void) -{ - if (ioready()) { - do { - (void) readl(bus_xfer); - DELAY(); - } while (ioready()); - } -} - -static u32 pic32_bus_readl(u32 reg) -{ - unsigned long flags; - u32 status, val; - - spin_lock_irqsave(&pic32_bus_lock, flags); - - check_ioclear(); - writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer); - DELAY(); - wait_ioready(); - status = readl(bus_xfer); - DELAY(); - val = readl(bus_xfer); - wait_ioclear(); - - spin_unlock_irqrestore(&pic32_bus_lock, flags); - - return val; -} - -static void pic32_bus_writel(u32 val, u32 reg) -{ - unsigned long flags; - u32 status; - - spin_lock_irqsave(&pic32_bus_lock, flags); - - check_ioclear(); - writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer); - DELAY(); - writel(val, bus_xfer); - DELAY(); - wait_ioready(); - status = readl(bus_xfer); - wait_ioclear(); - - spin_unlock_irqrestore(&pic32_bus_lock, flags); -} - -struct pic32_i2c_platform_data { - u32 base; - struct i2c_adapter adap; - u32 xfer_timeout; - u32 ack_timeout; - u32 ctl_timeout; -}; - -static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); - pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); - pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); -} - -static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap) -{ - int i; - - for (i = 0; i < adap->ctl_timeout; i++) { - if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & - (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN | - PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN | - PIC32_I2CCON_SEN)) == 0) && - ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - (PIC32_I2CSTAT_TRSTAT)) == 0)) - return 0; - udelay(1); - } - return -ETIMEDOUT; -} - -static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap, - u32 byte) -{ - pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); - return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - PIC32_I2CSTAT_IWCOL; -} - -static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); - while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN) - ; - pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); - return pic32_bus_readl(adap->base + PIC32_I2CxRCV); -} - -static int pic32_i2c_address(struct pic32_i2c_platform_data *adap, - unsigned int addr, int rd) -{ - pic32_i2c_idle(adap); - pic32_i2c_start(adap); - pic32_i2c_idle(adap); - - addr <<= 1; - if (rd) - addr |= 1; - - if (pic32_i2c_master_write(adap, addr)) - return -EIO; - pic32_i2c_idle(adap); - if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - PIC32_I2CSTAT_ACKSTAT) - return -EIO; - return 0; -} - -static int sead3_i2c_read(struct pic32_i2c_platform_data *adap, - unsigned char *buf, unsigned int len) -{ - u32 data; - int i; - - i = 0; - while (i < len) { - data = pic32_i2c_master_read(adap); - buf[i++] = data; - if (i < len) - pic32_i2c_ack(adap); - else - pic32_i2c_nack(adap); - } - - pic32_i2c_stop(adap); - pic32_i2c_idle(adap); - return 0; -} - -static int sead3_i2c_write(struct pic32_i2c_platform_data *adap, - unsigned char *buf, unsigned int len) -{ - int i; - u32 data; - - i = 0; - while (i < len) { - data = buf[i]; - if (pic32_i2c_master_write(adap, data)) - return -EIO; - pic32_i2c_idle(adap); - if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - PIC32_I2CSTAT_ACKSTAT) - return -EIO; - i++; - } - - pic32_i2c_stop(adap); - pic32_i2c_idle(adap); - return 0; -} - -static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - struct pic32_i2c_platform_data *adap = i2c_adap->algo_data; - struct i2c_msg *p; - int i, err = 0; - - for (i = 0; i < num; i++) { -#define __BUFSIZE 80 - int ii; - static char buf[__BUFSIZE]; - char *b = buf; - - p = &msgs[i]; - b += sprintf(buf, " [%d bytes]", p->len); - if ((p->flags & I2C_M_RD) == 0) { - for (ii = 0; ii < p->len; ii++) { - if (b < &buf[__BUFSIZE-4]) { - b += sprintf(b, " %02x", p->buf[ii]); - } else { - strcat(b, "..."); - break; - } - } - } - } - - for (i = 0; !err && i < num; i++) { - p = &msgs[i]; - err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD); - if (err || !p->len) - continue; - if (p->flags & I2C_M_RD) - err = sead3_i2c_read(adap, p->buf, p->len); - else - err = sead3_i2c_write(adap, p->buf, p->len); - } - - /* Return the number of messages processed, or the error code. */ - if (err == 0) - err = num; - - return err; -} - -static u32 sead3_pic32_platform_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm sead3_platform_algo = { - .master_xfer = sead3_pic32_platform_xfer, - .functionality = sead3_pic32_platform_func, -}; - -static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv) -{ - pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); - pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR); - pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET); - pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL, - priv->base + PIC32_I2CxSTATCLR); -} - -static int sead3_i2c_platform_probe(struct platform_device *pdev) -{ - struct pic32_i2c_platform_data *priv; - struct resource *r; - int ret; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - ret = -ENODEV; - goto out; - } - - priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto out; - } - - priv->base = r->start; - if (!priv->base) { - ret = -EBUSY; - goto out_mem; - } - - priv->xfer_timeout = 200; - priv->ack_timeout = 200; - priv->ctl_timeout = 200; - - priv->adap.nr = pdev->id; - priv->adap.algo = &sead3_platform_algo; - priv->adap.algo_data = priv; - priv->adap.dev.parent = &pdev->dev; - strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name)); - - sead3_i2c_platform_setup(priv); - - ret = i2c_add_numbered_adapter(&priv->adap); - if (ret == 0) { - platform_set_drvdata(pdev, priv); - return 0; - } - -out_mem: - kfree(priv); -out: - return ret; -} - -static int sead3_i2c_platform_remove(struct platform_device *pdev) -{ - struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - i2c_del_adapter(&priv->adap); - kfree(priv); - return 0; -} - -#ifdef CONFIG_PM -static int sead3_i2c_platform_suspend(struct platform_device *pdev, - pm_message_t state) -{ - dev_dbg(&pdev->dev, "i2c_platform_disable\n"); - return 0; -} - -static int sead3_i2c_platform_resume(struct platform_device *pdev) -{ - struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); - - dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n"); - sead3_i2c_platform_setup(priv); - - return 0; -} -#else -#define sead3_i2c_platform_suspend NULL -#define sead3_i2c_platform_resume NULL -#endif - -static struct platform_driver sead3_i2c_platform_driver = { - .driver = { - .name = "sead3-i2c", - .owner = THIS_MODULE, - }, - .probe = sead3_i2c_platform_probe, - .remove = sead3_i2c_platform_remove, - .suspend = sead3_i2c_platform_suspend, - .resume = sead3_i2c_platform_resume, -}; - -static int __init sead3_i2c_platform_init(void) -{ - return platform_driver_register(&sead3_i2c_platform_driver); -} -module_init(sead3_i2c_platform_init); - -static void __exit sead3_i2c_platform_exit(void) -{ - platform_driver_unregister(&sead3_i2c_platform_driver); -} -module_exit(sead3_i2c_platform_exit); - -MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); -MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 917c358..1e849d7 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -724,6 +724,13 @@ config I2C_S3C2410 Say Y here to include support for I2C controller in the Samsung SoCs. +config I2C_SEAD3 + tristate "SEAD3 I2C Driver" + depends on MIPS_SEAD3 + help + Say Y here to include support for I2C controller on the + MIPS SEAD3 evaluation board. + config I2C_SH7760 tristate "Renesas SH7760 I2C Controller" depends on CPU_SUBTYPE_SH7760 diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 78d56c5..ec255db 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_I2C_QUP) += i2c-qup.o obj-$(CONFIG_I2C_RIIC) += i2c-riic.o obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o +obj-$(CONFIG_I2C_SEAD3) += i2c-sead3.o obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o diff --git a/drivers/i2c/busses/i2c-sead3.c b/drivers/i2c/busses/i2c-sead3.c new file mode 100644 index 0000000..1f787a6 --- /dev/null +++ b/drivers/i2c/busses/i2c-sead3.c @@ -0,0 +1,405 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/platform_device.h> + +#define PIC32_I2CxCON 0x0000 +#define PIC32_I2CCON_ON (1<<15) +#define PIC32_I2CCON_ACKDT (1<<5) +#define PIC32_I2CCON_ACKEN (1<<4) +#define PIC32_I2CCON_RCEN (1<<3) +#define PIC32_I2CCON_PEN (1<<2) +#define PIC32_I2CCON_RSEN (1<<1) +#define PIC32_I2CCON_SEN (1<<0) +#define PIC32_I2CxCONCLR 0x0004 +#define PIC32_I2CxCONSET 0x0008 +#define PIC32_I2CxSTAT 0x0010 +#define PIC32_I2CxSTATCLR 0x0014 +#define PIC32_I2CSTAT_ACKSTAT (1<<15) +#define PIC32_I2CSTAT_TRSTAT (1<<14) +#define PIC32_I2CSTAT_BCL (1<<10) +#define PIC32_I2CSTAT_IWCOL (1<<7) +#define PIC32_I2CSTAT_I2COV (1<<6) +#define PIC32_I2CxBRG 0x0040 +#define PIC32_I2CxTRN 0x0050 +#define PIC32_I2CxRCV 0x0060 + +static DEFINE_SPINLOCK(pic32_bus_lock); + +static void __iomem *bus_xfer = (void __iomem *)0xbf000600; +static void __iomem *bus_status = (void __iomem *)0xbf000060; + +#define DELAY() udelay(100) + +static inline unsigned int ioready(void) +{ + return readl(bus_status) & 1; +} + +static inline void wait_ioready(void) +{ + do { } while (!ioready()); +} + +static inline void wait_ioclear(void) +{ + do { } while (ioready()); +} + +static inline void check_ioclear(void) +{ + if (ioready()) { + do { + (void) readl(bus_xfer); + DELAY(); + } while (ioready()); + } +} + +static u32 pic32_bus_readl(u32 reg) +{ + unsigned long flags; + u32 status, val; + + spin_lock_irqsave(&pic32_bus_lock, flags); + + check_ioclear(); + writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer); + DELAY(); + wait_ioready(); + status = readl(bus_xfer); + DELAY(); + val = readl(bus_xfer); + wait_ioclear(); + + spin_unlock_irqrestore(&pic32_bus_lock, flags); + + return val; +} + +static void pic32_bus_writel(u32 val, u32 reg) +{ + unsigned long flags; + u32 status; + + spin_lock_irqsave(&pic32_bus_lock, flags); + + check_ioclear(); + writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer); + DELAY(); + writel(val, bus_xfer); + DELAY(); + wait_ioready(); + status = readl(bus_xfer); + wait_ioclear(); + + spin_unlock_irqrestore(&pic32_bus_lock, flags); +} + +struct pic32_i2c_platform_data { + u32 base; + struct i2c_adapter adap; + u32 xfer_timeout; + u32 ack_timeout; + u32 ctl_timeout; +}; + +static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET); +} + +static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET); +} + +static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); + pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); +} + +static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); + pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); +} + +static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap) +{ + int i; + + for (i = 0; i < adap->ctl_timeout; i++) { + if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & + (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN | + PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN | + PIC32_I2CCON_SEN)) == 0) && + ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & + (PIC32_I2CSTAT_TRSTAT)) == 0)) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap, + u32 byte) +{ + pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); + return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & + PIC32_I2CSTAT_IWCOL; +} + +static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); + while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN) + ; + pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); + return pic32_bus_readl(adap->base + PIC32_I2CxRCV); +} + +static int pic32_i2c_address(struct pic32_i2c_platform_data *adap, + unsigned int addr, int rd) +{ + pic32_i2c_idle(adap); + pic32_i2c_start(adap); + pic32_i2c_idle(adap); + + addr <<= 1; + if (rd) + addr |= 1; + + if (pic32_i2c_master_write(adap, addr)) + return -EIO; + pic32_i2c_idle(adap); + if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & + PIC32_I2CSTAT_ACKSTAT) + return -EIO; + return 0; +} + +static int sead3_i2c_read(struct pic32_i2c_platform_data *adap, + unsigned char *buf, unsigned int len) +{ + u32 data; + int i; + + i = 0; + while (i < len) { + data = pic32_i2c_master_read(adap); + buf[i++] = data; + if (i < len) + pic32_i2c_ack(adap); + else + pic32_i2c_nack(adap); + } + + pic32_i2c_stop(adap); + pic32_i2c_idle(adap); + return 0; +} + +static int sead3_i2c_write(struct pic32_i2c_platform_data *adap, + unsigned char *buf, unsigned int len) +{ + int i; + u32 data; + + i = 0; + while (i < len) { + data = buf[i]; + if (pic32_i2c_master_write(adap, data)) + return -EIO; + pic32_i2c_idle(adap); + if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & + PIC32_I2CSTAT_ACKSTAT) + return -EIO; + i++; + } + + pic32_i2c_stop(adap); + pic32_i2c_idle(adap); + return 0; +} + +static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + struct pic32_i2c_platform_data *adap = i2c_adap->algo_data; + struct i2c_msg *p; + int i, err = 0; + + for (i = 0; i < num; i++) { +#define __BUFSIZE 80 + int ii; + static char buf[__BUFSIZE]; + char *b = buf; + + p = &msgs[i]; + b += sprintf(buf, " [%d bytes]", p->len); + if ((p->flags & I2C_M_RD) == 0) { + for (ii = 0; ii < p->len; ii++) { + if (b < &buf[__BUFSIZE-4]) { + b += sprintf(b, " %02x", p->buf[ii]); + } else { + strcat(b, "..."); + break; + } + } + } + } + + for (i = 0; !err && i < num; i++) { + p = &msgs[i]; + err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD); + if (err || !p->len) + continue; + if (p->flags & I2C_M_RD) + err = sead3_i2c_read(adap, p->buf, p->len); + else + err = sead3_i2c_write(adap, p->buf, p->len); + } + + /* Return the number of messages processed, or the error code. */ + if (err == 0) + err = num; + + return err; +} + +static u32 sead3_pic32_platform_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm sead3_platform_algo = { + .master_xfer = sead3_pic32_platform_xfer, + .functionality = sead3_pic32_platform_func, +}; + +static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv) +{ + pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); + pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR); + pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET); + pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL, + priv->base + PIC32_I2CxSTATCLR); +} + +static int sead3_i2c_platform_probe(struct platform_device *pdev) +{ + struct pic32_i2c_platform_data *priv; + struct resource *r; + int ret; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + ret = -ENODEV; + goto out; + } + + priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto out; + } + + priv->base = r->start; + if (!priv->base) { + ret = -EBUSY; + goto out_mem; + } + + priv->xfer_timeout = 200; + priv->ack_timeout = 200; + priv->ctl_timeout = 200; + + priv->adap.nr = pdev->id; + priv->adap.algo = &sead3_platform_algo; + priv->adap.algo_data = priv; + priv->adap.dev.parent = &pdev->dev; + strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name)); + + sead3_i2c_platform_setup(priv); + + ret = i2c_add_numbered_adapter(&priv->adap); + if (ret == 0) { + platform_set_drvdata(pdev, priv); + return 0; + } + +out_mem: + kfree(priv); +out: + return ret; +} + +static int sead3_i2c_platform_remove(struct platform_device *pdev) +{ + struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + i2c_del_adapter(&priv->adap); + kfree(priv); + return 0; +} + +#ifdef CONFIG_PM +static int sead3_i2c_platform_suspend(struct platform_device *pdev, + pm_message_t state) +{ + dev_dbg(&pdev->dev, "i2c_platform_disable\n"); + return 0; +} + +static int sead3_i2c_platform_resume(struct platform_device *pdev) +{ + struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); + + dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n"); + sead3_i2c_platform_setup(priv); + + return 0; +} +#else +#define sead3_i2c_platform_suspend NULL +#define sead3_i2c_platform_resume NULL +#endif + +static struct platform_driver sead3_i2c_platform_driver = { + .driver = { + .name = "sead3-i2c", + .owner = THIS_MODULE, + }, + .probe = sead3_i2c_platform_probe, + .remove = sead3_i2c_platform_remove, + .suspend = sead3_i2c_platform_suspend, + .resume = sead3_i2c_platform_resume, +}; + +static int __init sead3_i2c_platform_init(void) +{ + return platform_driver_register(&sead3_i2c_platform_driver); +} +module_init(sead3_i2c_platform_init); + +static void __exit sead3_i2c_platform_exit(void) +{ + platform_driver_unregister(&sead3_i2c_platform_driver); +} +module_exit(sead3_i2c_platform_exit); + +MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); +MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver"); +MODULE_LICENSE("GPL"); ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH] MIPS/I2C: Move SEAD3 I2C driver to where it belongs. @ 2014-10-24 12:26 ` Ralf Baechle 0 siblings, 0 replies; 20+ messages in thread From: Ralf Baechle @ 2014-10-24 12:26 UTC (permalink / raw) To: Markos Chandras, Wolfram Sang, linux-i2c; +Cc: linux-mips, Chris Dearman Fixes the following build problem if CONFIG_I2C is disabled: arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_probe': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:345:2: error: implicit declaration of function 'i2c_add_numbered_adapter' [-Werror=implicit-function-declaration] ret = i2c_add_numbered_adapter(&priv->adap); ^ arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_remove': arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:361:2: error: implicit declaration of function 'i2c_del_adapter' [-Werror=implicit-function-declaration] i2c_del_adapter(&priv->adap); Signed-off-by: Ralf Baechle <ralf@linux-mips.org> Cc: Markos Chandras <markos.chandras@imgtec.com> Cc: Wolfram Sang <wsa@the-dreams.de> Cc: linux-i2c@vger.kernel.org Cc: linux-mips@linux-mips.org Cc: Chris Dearman <chris.dearman@imgtec.com> diff --git a/arch/mips/mti-sead3/sead3-i2c-drv.c b/arch/mips/mti-sead3/sead3-i2c-drv.c deleted file mode 100644 index 1f787a6..0000000 --- a/arch/mips/mti-sead3/sead3-i2c-drv.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> - -#define PIC32_I2CxCON 0x0000 -#define PIC32_I2CCON_ON (1<<15) -#define PIC32_I2CCON_ACKDT (1<<5) -#define PIC32_I2CCON_ACKEN (1<<4) -#define PIC32_I2CCON_RCEN (1<<3) -#define PIC32_I2CCON_PEN (1<<2) -#define PIC32_I2CCON_RSEN (1<<1) -#define PIC32_I2CCON_SEN (1<<0) -#define PIC32_I2CxCONCLR 0x0004 -#define PIC32_I2CxCONSET 0x0008 -#define PIC32_I2CxSTAT 0x0010 -#define PIC32_I2CxSTATCLR 0x0014 -#define PIC32_I2CSTAT_ACKSTAT (1<<15) -#define PIC32_I2CSTAT_TRSTAT (1<<14) -#define PIC32_I2CSTAT_BCL (1<<10) -#define PIC32_I2CSTAT_IWCOL (1<<7) -#define PIC32_I2CSTAT_I2COV (1<<6) -#define PIC32_I2CxBRG 0x0040 -#define PIC32_I2CxTRN 0x0050 -#define PIC32_I2CxRCV 0x0060 - -static DEFINE_SPINLOCK(pic32_bus_lock); - -static void __iomem *bus_xfer = (void __iomem *)0xbf000600; -static void __iomem *bus_status = (void __iomem *)0xbf000060; - -#define DELAY() udelay(100) - -static inline unsigned int ioready(void) -{ - return readl(bus_status) & 1; -} - -static inline void wait_ioready(void) -{ - do { } while (!ioready()); -} - -static inline void wait_ioclear(void) -{ - do { } while (ioready()); -} - -static inline void check_ioclear(void) -{ - if (ioready()) { - do { - (void) readl(bus_xfer); - DELAY(); - } while (ioready()); - } -} - -static u32 pic32_bus_readl(u32 reg) -{ - unsigned long flags; - u32 status, val; - - spin_lock_irqsave(&pic32_bus_lock, flags); - - check_ioclear(); - writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer); - DELAY(); - wait_ioready(); - status = readl(bus_xfer); - DELAY(); - val = readl(bus_xfer); - wait_ioclear(); - - spin_unlock_irqrestore(&pic32_bus_lock, flags); - - return val; -} - -static void pic32_bus_writel(u32 val, u32 reg) -{ - unsigned long flags; - u32 status; - - spin_lock_irqsave(&pic32_bus_lock, flags); - - check_ioclear(); - writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer); - DELAY(); - writel(val, bus_xfer); - DELAY(); - wait_ioready(); - status = readl(bus_xfer); - wait_ioclear(); - - spin_unlock_irqrestore(&pic32_bus_lock, flags); -} - -struct pic32_i2c_platform_data { - u32 base; - struct i2c_adapter adap; - u32 xfer_timeout; - u32 ack_timeout; - u32 ctl_timeout; -}; - -static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); - pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); -} - -static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); - pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); -} - -static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap) -{ - int i; - - for (i = 0; i < adap->ctl_timeout; i++) { - if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & - (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN | - PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN | - PIC32_I2CCON_SEN)) == 0) && - ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - (PIC32_I2CSTAT_TRSTAT)) == 0)) - return 0; - udelay(1); - } - return -ETIMEDOUT; -} - -static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap, - u32 byte) -{ - pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); - return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - PIC32_I2CSTAT_IWCOL; -} - -static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap) -{ - pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); - while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN) - ; - pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); - return pic32_bus_readl(adap->base + PIC32_I2CxRCV); -} - -static int pic32_i2c_address(struct pic32_i2c_platform_data *adap, - unsigned int addr, int rd) -{ - pic32_i2c_idle(adap); - pic32_i2c_start(adap); - pic32_i2c_idle(adap); - - addr <<= 1; - if (rd) - addr |= 1; - - if (pic32_i2c_master_write(adap, addr)) - return -EIO; - pic32_i2c_idle(adap); - if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - PIC32_I2CSTAT_ACKSTAT) - return -EIO; - return 0; -} - -static int sead3_i2c_read(struct pic32_i2c_platform_data *adap, - unsigned char *buf, unsigned int len) -{ - u32 data; - int i; - - i = 0; - while (i < len) { - data = pic32_i2c_master_read(adap); - buf[i++] = data; - if (i < len) - pic32_i2c_ack(adap); - else - pic32_i2c_nack(adap); - } - - pic32_i2c_stop(adap); - pic32_i2c_idle(adap); - return 0; -} - -static int sead3_i2c_write(struct pic32_i2c_platform_data *adap, - unsigned char *buf, unsigned int len) -{ - int i; - u32 data; - - i = 0; - while (i < len) { - data = buf[i]; - if (pic32_i2c_master_write(adap, data)) - return -EIO; - pic32_i2c_idle(adap); - if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & - PIC32_I2CSTAT_ACKSTAT) - return -EIO; - i++; - } - - pic32_i2c_stop(adap); - pic32_i2c_idle(adap); - return 0; -} - -static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - struct pic32_i2c_platform_data *adap = i2c_adap->algo_data; - struct i2c_msg *p; - int i, err = 0; - - for (i = 0; i < num; i++) { -#define __BUFSIZE 80 - int ii; - static char buf[__BUFSIZE]; - char *b = buf; - - p = &msgs[i]; - b += sprintf(buf, " [%d bytes]", p->len); - if ((p->flags & I2C_M_RD) == 0) { - for (ii = 0; ii < p->len; ii++) { - if (b < &buf[__BUFSIZE-4]) { - b += sprintf(b, " %02x", p->buf[ii]); - } else { - strcat(b, "..."); - break; - } - } - } - } - - for (i = 0; !err && i < num; i++) { - p = &msgs[i]; - err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD); - if (err || !p->len) - continue; - if (p->flags & I2C_M_RD) - err = sead3_i2c_read(adap, p->buf, p->len); - else - err = sead3_i2c_write(adap, p->buf, p->len); - } - - /* Return the number of messages processed, or the error code. */ - if (err == 0) - err = num; - - return err; -} - -static u32 sead3_pic32_platform_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm sead3_platform_algo = { - .master_xfer = sead3_pic32_platform_xfer, - .functionality = sead3_pic32_platform_func, -}; - -static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv) -{ - pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); - pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR); - pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET); - pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL, - priv->base + PIC32_I2CxSTATCLR); -} - -static int sead3_i2c_platform_probe(struct platform_device *pdev) -{ - struct pic32_i2c_platform_data *priv; - struct resource *r; - int ret; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - ret = -ENODEV; - goto out; - } - - priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto out; - } - - priv->base = r->start; - if (!priv->base) { - ret = -EBUSY; - goto out_mem; - } - - priv->xfer_timeout = 200; - priv->ack_timeout = 200; - priv->ctl_timeout = 200; - - priv->adap.nr = pdev->id; - priv->adap.algo = &sead3_platform_algo; - priv->adap.algo_data = priv; - priv->adap.dev.parent = &pdev->dev; - strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name)); - - sead3_i2c_platform_setup(priv); - - ret = i2c_add_numbered_adapter(&priv->adap); - if (ret == 0) { - platform_set_drvdata(pdev, priv); - return 0; - } - -out_mem: - kfree(priv); -out: - return ret; -} - -static int sead3_i2c_platform_remove(struct platform_device *pdev) -{ - struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - i2c_del_adapter(&priv->adap); - kfree(priv); - return 0; -} - -#ifdef CONFIG_PM -static int sead3_i2c_platform_suspend(struct platform_device *pdev, - pm_message_t state) -{ - dev_dbg(&pdev->dev, "i2c_platform_disable\n"); - return 0; -} - -static int sead3_i2c_platform_resume(struct platform_device *pdev) -{ - struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); - - dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n"); - sead3_i2c_platform_setup(priv); - - return 0; -} -#else -#define sead3_i2c_platform_suspend NULL -#define sead3_i2c_platform_resume NULL -#endif - -static struct platform_driver sead3_i2c_platform_driver = { - .driver = { - .name = "sead3-i2c", - .owner = THIS_MODULE, - }, - .probe = sead3_i2c_platform_probe, - .remove = sead3_i2c_platform_remove, - .suspend = sead3_i2c_platform_suspend, - .resume = sead3_i2c_platform_resume, -}; - -static int __init sead3_i2c_platform_init(void) -{ - return platform_driver_register(&sead3_i2c_platform_driver); -} -module_init(sead3_i2c_platform_init); - -static void __exit sead3_i2c_platform_exit(void) -{ - platform_driver_unregister(&sead3_i2c_platform_driver); -} -module_exit(sead3_i2c_platform_exit); - -MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); -MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 917c358..1e849d7 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -724,6 +724,13 @@ config I2C_S3C2410 Say Y here to include support for I2C controller in the Samsung SoCs. +config I2C_SEAD3 + tristate "SEAD3 I2C Driver" + depends on MIPS_SEAD3 + help + Say Y here to include support for I2C controller on the + MIPS SEAD3 evaluation board. + config I2C_SH7760 tristate "Renesas SH7760 I2C Controller" depends on CPU_SUBTYPE_SH7760 diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 78d56c5..ec255db 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_I2C_QUP) += i2c-qup.o obj-$(CONFIG_I2C_RIIC) += i2c-riic.o obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o +obj-$(CONFIG_I2C_SEAD3) += i2c-sead3.o obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o diff --git a/drivers/i2c/busses/i2c-sead3.c b/drivers/i2c/busses/i2c-sead3.c new file mode 100644 index 0000000..1f787a6 --- /dev/null +++ b/drivers/i2c/busses/i2c-sead3.c @@ -0,0 +1,405 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/platform_device.h> + +#define PIC32_I2CxCON 0x0000 +#define PIC32_I2CCON_ON (1<<15) +#define PIC32_I2CCON_ACKDT (1<<5) +#define PIC32_I2CCON_ACKEN (1<<4) +#define PIC32_I2CCON_RCEN (1<<3) +#define PIC32_I2CCON_PEN (1<<2) +#define PIC32_I2CCON_RSEN (1<<1) +#define PIC32_I2CCON_SEN (1<<0) +#define PIC32_I2CxCONCLR 0x0004 +#define PIC32_I2CxCONSET 0x0008 +#define PIC32_I2CxSTAT 0x0010 +#define PIC32_I2CxSTATCLR 0x0014 +#define PIC32_I2CSTAT_ACKSTAT (1<<15) +#define PIC32_I2CSTAT_TRSTAT (1<<14) +#define PIC32_I2CSTAT_BCL (1<<10) +#define PIC32_I2CSTAT_IWCOL (1<<7) +#define PIC32_I2CSTAT_I2COV (1<<6) +#define PIC32_I2CxBRG 0x0040 +#define PIC32_I2CxTRN 0x0050 +#define PIC32_I2CxRCV 0x0060 + +static DEFINE_SPINLOCK(pic32_bus_lock); + +static void __iomem *bus_xfer = (void __iomem *)0xbf000600; +static void __iomem *bus_status = (void __iomem *)0xbf000060; + +#define DELAY() udelay(100) + +static inline unsigned int ioready(void) +{ + return readl(bus_status) & 1; +} + +static inline void wait_ioready(void) +{ + do { } while (!ioready()); +} + +static inline void wait_ioclear(void) +{ + do { } while (ioready()); +} + +static inline void check_ioclear(void) +{ + if (ioready()) { + do { + (void) readl(bus_xfer); + DELAY(); + } while (ioready()); + } +} + +static u32 pic32_bus_readl(u32 reg) +{ + unsigned long flags; + u32 status, val; + + spin_lock_irqsave(&pic32_bus_lock, flags); + + check_ioclear(); + writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer); + DELAY(); + wait_ioready(); + status = readl(bus_xfer); + DELAY(); + val = readl(bus_xfer); + wait_ioclear(); + + spin_unlock_irqrestore(&pic32_bus_lock, flags); + + return val; +} + +static void pic32_bus_writel(u32 val, u32 reg) +{ + unsigned long flags; + u32 status; + + spin_lock_irqsave(&pic32_bus_lock, flags); + + check_ioclear(); + writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer); + DELAY(); + writel(val, bus_xfer); + DELAY(); + wait_ioready(); + status = readl(bus_xfer); + wait_ioclear(); + + spin_unlock_irqrestore(&pic32_bus_lock, flags); +} + +struct pic32_i2c_platform_data { + u32 base; + struct i2c_adapter adap; + u32 xfer_timeout; + u32 ack_timeout; + u32 ctl_timeout; +}; + +static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET); +} + +static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET); +} + +static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); + pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); +} + +static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); + pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); +} + +static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap) +{ + int i; + + for (i = 0; i < adap->ctl_timeout; i++) { + if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & + (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN | + PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN | + PIC32_I2CCON_SEN)) == 0) && + ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & + (PIC32_I2CSTAT_TRSTAT)) == 0)) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap, + u32 byte) +{ + pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); + return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & + PIC32_I2CSTAT_IWCOL; +} + +static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap) +{ + pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); + while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN) + ; + pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); + return pic32_bus_readl(adap->base + PIC32_I2CxRCV); +} + +static int pic32_i2c_address(struct pic32_i2c_platform_data *adap, + unsigned int addr, int rd) +{ + pic32_i2c_idle(adap); + pic32_i2c_start(adap); + pic32_i2c_idle(adap); + + addr <<= 1; + if (rd) + addr |= 1; + + if (pic32_i2c_master_write(adap, addr)) + return -EIO; + pic32_i2c_idle(adap); + if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & + PIC32_I2CSTAT_ACKSTAT) + return -EIO; + return 0; +} + +static int sead3_i2c_read(struct pic32_i2c_platform_data *adap, + unsigned char *buf, unsigned int len) +{ + u32 data; + int i; + + i = 0; + while (i < len) { + data = pic32_i2c_master_read(adap); + buf[i++] = data; + if (i < len) + pic32_i2c_ack(adap); + else + pic32_i2c_nack(adap); + } + + pic32_i2c_stop(adap); + pic32_i2c_idle(adap); + return 0; +} + +static int sead3_i2c_write(struct pic32_i2c_platform_data *adap, + unsigned char *buf, unsigned int len) +{ + int i; + u32 data; + + i = 0; + while (i < len) { + data = buf[i]; + if (pic32_i2c_master_write(adap, data)) + return -EIO; + pic32_i2c_idle(adap); + if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & + PIC32_I2CSTAT_ACKSTAT) + return -EIO; + i++; + } + + pic32_i2c_stop(adap); + pic32_i2c_idle(adap); + return 0; +} + +static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + struct pic32_i2c_platform_data *adap = i2c_adap->algo_data; + struct i2c_msg *p; + int i, err = 0; + + for (i = 0; i < num; i++) { +#define __BUFSIZE 80 + int ii; + static char buf[__BUFSIZE]; + char *b = buf; + + p = &msgs[i]; + b += sprintf(buf, " [%d bytes]", p->len); + if ((p->flags & I2C_M_RD) == 0) { + for (ii = 0; ii < p->len; ii++) { + if (b < &buf[__BUFSIZE-4]) { + b += sprintf(b, " %02x", p->buf[ii]); + } else { + strcat(b, "..."); + break; + } + } + } + } + + for (i = 0; !err && i < num; i++) { + p = &msgs[i]; + err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD); + if (err || !p->len) + continue; + if (p->flags & I2C_M_RD) + err = sead3_i2c_read(adap, p->buf, p->len); + else + err = sead3_i2c_write(adap, p->buf, p->len); + } + + /* Return the number of messages processed, or the error code. */ + if (err == 0) + err = num; + + return err; +} + +static u32 sead3_pic32_platform_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm sead3_platform_algo = { + .master_xfer = sead3_pic32_platform_xfer, + .functionality = sead3_pic32_platform_func, +}; + +static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv) +{ + pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); + pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR); + pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET); + pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL, + priv->base + PIC32_I2CxSTATCLR); +} + +static int sead3_i2c_platform_probe(struct platform_device *pdev) +{ + struct pic32_i2c_platform_data *priv; + struct resource *r; + int ret; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + ret = -ENODEV; + goto out; + } + + priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto out; + } + + priv->base = r->start; + if (!priv->base) { + ret = -EBUSY; + goto out_mem; + } + + priv->xfer_timeout = 200; + priv->ack_timeout = 200; + priv->ctl_timeout = 200; + + priv->adap.nr = pdev->id; + priv->adap.algo = &sead3_platform_algo; + priv->adap.algo_data = priv; + priv->adap.dev.parent = &pdev->dev; + strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name)); + + sead3_i2c_platform_setup(priv); + + ret = i2c_add_numbered_adapter(&priv->adap); + if (ret == 0) { + platform_set_drvdata(pdev, priv); + return 0; + } + +out_mem: + kfree(priv); +out: + return ret; +} + +static int sead3_i2c_platform_remove(struct platform_device *pdev) +{ + struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + i2c_del_adapter(&priv->adap); + kfree(priv); + return 0; +} + +#ifdef CONFIG_PM +static int sead3_i2c_platform_suspend(struct platform_device *pdev, + pm_message_t state) +{ + dev_dbg(&pdev->dev, "i2c_platform_disable\n"); + return 0; +} + +static int sead3_i2c_platform_resume(struct platform_device *pdev) +{ + struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); + + dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n"); + sead3_i2c_platform_setup(priv); + + return 0; +} +#else +#define sead3_i2c_platform_suspend NULL +#define sead3_i2c_platform_resume NULL +#endif + +static struct platform_driver sead3_i2c_platform_driver = { + .driver = { + .name = "sead3-i2c", + .owner = THIS_MODULE, + }, + .probe = sead3_i2c_platform_probe, + .remove = sead3_i2c_platform_remove, + .suspend = sead3_i2c_platform_suspend, + .resume = sead3_i2c_platform_resume, +}; + +static int __init sead3_i2c_platform_init(void) +{ + return platform_driver_register(&sead3_i2c_platform_driver); +} +module_init(sead3_i2c_platform_init); + +static void __exit sead3_i2c_platform_exit(void) +{ + platform_driver_unregister(&sead3_i2c_platform_driver); +} +module_exit(sead3_i2c_platform_exit); + +MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); +MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver"); +MODULE_LICENSE("GPL"); ^ permalink raw reply related [flat|nested] 20+ messages in thread
[parent not found: <20141024122656.GC12641-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>]
* Re: [PATCH] MIPS/I2C: Move SEAD3 I2C driver to where it belongs. 2014-10-24 12:26 ` Ralf Baechle @ 2014-11-13 8:24 ` Wolfram Sang -1 siblings, 0 replies; 20+ messages in thread From: Wolfram Sang @ 2014-11-13 8:24 UTC (permalink / raw) To: Ralf Baechle Cc: Markos Chandras, linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-mips-6z/3iImG2C8G8FEW9MqTrA, Chris Dearman [-- Attachment #1: Type: text/plain, Size: 13151 bytes --] On Fri, Oct 24, 2014 at 02:26:57PM +0200, Ralf Baechle wrote: > Fixes the following build problem if CONFIG_I2C is disabled: > > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_probe': > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:345:2: error: implicit declaration of > function 'i2c_add_numbered_adapter' [-Werror=implicit-function-declaration] > ret = i2c_add_numbered_adapter(&priv->adap); > ^ > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function > 'i2c_platform_remove': > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:361:2: error: implicit declaration > of function 'i2c_del_adapter' [-Werror=implicit-function-declaration] > i2c_del_adapter(&priv->adap); > Uh, so this is already mainline? It has some issues. > Signed-off-by: Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org> > Cc: Markos Chandras <markos.chandras-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org> > Cc: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> > Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org > Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org > Cc: Chris Dearman <chris.dearman-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org> No diffstat? > diff --git a/drivers/i2c/busses/i2c-sead3.c b/drivers/i2c/busses/i2c-sead3.c > new file mode 100644 > index 0000000..1f787a6 > --- /dev/null > +++ b/drivers/i2c/busses/i2c-sead3.c > @@ -0,0 +1,405 @@ > +/* > + * This file is subject to the terms and conditions of the GNU General Public > + * License. See the file "COPYING" in the main directory of this archive > + * for more details. > + * > + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. > + */ > +#include <linux/init.h> > +#include <linux/module.h> > +#include <linux/slab.h> > +#include <linux/delay.h> > +#include <linux/i2c.h> > +#include <linux/platform_device.h> Please sort the includes. > + > +#define PIC32_I2CxCON 0x0000 > +#define PIC32_I2CCON_ON (1<<15) > +#define PIC32_I2CCON_ACKDT (1<<5) > +#define PIC32_I2CCON_ACKEN (1<<4) > +#define PIC32_I2CCON_RCEN (1<<3) > +#define PIC32_I2CCON_PEN (1<<2) > +#define PIC32_I2CCON_RSEN (1<<1) > +#define PIC32_I2CCON_SEN (1<<0) > +#define PIC32_I2CxCONCLR 0x0004 > +#define PIC32_I2CxCONSET 0x0008 > +#define PIC32_I2CxSTAT 0x0010 > +#define PIC32_I2CxSTATCLR 0x0014 > +#define PIC32_I2CSTAT_ACKSTAT (1<<15) > +#define PIC32_I2CSTAT_TRSTAT (1<<14) > +#define PIC32_I2CSTAT_BCL (1<<10) > +#define PIC32_I2CSTAT_IWCOL (1<<7) > +#define PIC32_I2CSTAT_I2COV (1<<6) > +#define PIC32_I2CxBRG 0x0040 > +#define PIC32_I2CxTRN 0x0050 > +#define PIC32_I2CxRCV 0x0060 > + > +static DEFINE_SPINLOCK(pic32_bus_lock); > + > +static void __iomem *bus_xfer = (void __iomem *)0xbf000600; > +static void __iomem *bus_status = (void __iomem *)0xbf000060; > + > +#define DELAY() udelay(100) > + > +static inline unsigned int ioready(void) > +{ > + return readl(bus_status) & 1; > +} > + > +static inline void wait_ioready(void) > +{ > + do { } while (!ioready()); > +} No timeout? > + > +static inline void wait_ioclear(void) > +{ > + do { } while (ioready()); > +} ditto > + > +static inline void check_ioclear(void) > +{ > + if (ioready()) { > + do { > + (void) readl(bus_xfer); > + DELAY(); > + } while (ioready()); > + } > +} > + > +static u32 pic32_bus_readl(u32 reg) > +{ > + unsigned long flags; > + u32 status, val; > + > + spin_lock_irqsave(&pic32_bus_lock, flags); > + > + check_ioclear(); > + writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer); Can we have names for all these magic hex-values? > + DELAY(); > + wait_ioready(); > + status = readl(bus_xfer); > + DELAY(); > + val = readl(bus_xfer); > + wait_ioclear(); > + > + spin_unlock_irqrestore(&pic32_bus_lock, flags); > + > + return val; > +} > + > +static void pic32_bus_writel(u32 val, u32 reg) > +{ > + unsigned long flags; > + u32 status; > + > + spin_lock_irqsave(&pic32_bus_lock, flags); > + > + check_ioclear(); > + writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer); > + DELAY(); > + writel(val, bus_xfer); > + DELAY(); > + wait_ioready(); > + status = readl(bus_xfer); > + wait_ioclear(); > + > + spin_unlock_irqrestore(&pic32_bus_lock, flags); > +} > + > +struct pic32_i2c_platform_data { > + u32 base; > + struct i2c_adapter adap; > + u32 xfer_timeout; > + u32 ack_timeout; > + u32 ctl_timeout; > +}; priv goes to the platform instead of the adapter? Unusual, why is that? > + > +static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET); > +} > + > +static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET); > +} > + > +static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); > + pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); > +} > + > +static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); > + pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); > +} > + > +static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap) > +{ > + int i; > + > + for (i = 0; i < adap->ctl_timeout; i++) { > + if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & > + (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN | > + PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN | > + PIC32_I2CCON_SEN)) == 0) && > + ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & > + (PIC32_I2CSTAT_TRSTAT)) == 0)) > + return 0; > + udelay(1); > + } > + return -ETIMEDOUT; > +} > + > +static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap, > + u32 byte) > +{ > + pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); > + return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & > + PIC32_I2CSTAT_IWCOL; > +} > + > +static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); > + while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN) > + ; > + pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); > + return pic32_bus_readl(adap->base + PIC32_I2CxRCV); > +} > + > +static int pic32_i2c_address(struct pic32_i2c_platform_data *adap, > + unsigned int addr, int rd) > +{ > + pic32_i2c_idle(adap); > + pic32_i2c_start(adap); > + pic32_i2c_idle(adap); > + > + addr <<= 1; > + if (rd) > + addr |= 1; > + > + if (pic32_i2c_master_write(adap, addr)) > + return -EIO; > + pic32_i2c_idle(adap); > + if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & > + PIC32_I2CSTAT_ACKSTAT) > + return -EIO; I'd think this is -ENXIO. Please have a look at Documentation/i2c/fault-codes for the error codes we use. > + return 0; > +} > + > +static int sead3_i2c_read(struct pic32_i2c_platform_data *adap, > + unsigned char *buf, unsigned int len) > +{ > + u32 data; > + int i; > + > + i = 0; > + while (i < len) { > + data = pic32_i2c_master_read(adap); > + buf[i++] = data; > + if (i < len) > + pic32_i2c_ack(adap); > + else > + pic32_i2c_nack(adap); > + } > + > + pic32_i2c_stop(adap); > + pic32_i2c_idle(adap); > + return 0; > +} > + > +static int sead3_i2c_write(struct pic32_i2c_platform_data *adap, > + unsigned char *buf, unsigned int len) > +{ > + int i; > + u32 data; > + > + i = 0; > + while (i < len) { > + data = buf[i]; > + if (pic32_i2c_master_write(adap, data)) > + return -EIO; > + pic32_i2c_idle(adap); > + if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & > + PIC32_I2CSTAT_ACKSTAT) > + return -EIO; ditto > + i++; > + } > + > + pic32_i2c_stop(adap); > + pic32_i2c_idle(adap); > + return 0; > +} > + > +static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap, > + struct i2c_msg *msgs, int num) > +{ > + struct pic32_i2c_platform_data *adap = i2c_adap->algo_data; > + struct i2c_msg *p; > + int i, err = 0; > + > + for (i = 0; i < num; i++) { > +#define __BUFSIZE 80 > + int ii; > + static char buf[__BUFSIZE]; > + char *b = buf; > + > + p = &msgs[i]; > + b += sprintf(buf, " [%d bytes]", p->len); > + if ((p->flags & I2C_M_RD) == 0) { > + for (ii = 0; ii < p->len; ii++) { > + if (b < &buf[__BUFSIZE-4]) { > + b += sprintf(b, " %02x", p->buf[ii]); > + } else { > + strcat(b, "..."); > + break; > + } > + } > + } ??? Where is buf used? And we have other debugging options and support even tracing. Not needed. > + } > + > + for (i = 0; !err && i < num; i++) { > + p = &msgs[i]; > + err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD); > + if (err || !p->len) > + continue; So, you don't support SMBUS_QUICK? You should remove it from the functionality then. Or add support for it. > + if (p->flags & I2C_M_RD) > + err = sead3_i2c_read(adap, p->buf, p->len); > + else > + err = sead3_i2c_write(adap, p->buf, p->len); > + } > + > + /* Return the number of messages processed, or the error code. */ > + if (err == 0) > + err = num; > + > + return err; > +} > + > +static u32 sead3_pic32_platform_func(struct i2c_adapter *adap) > +{ > + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; > +} > + > +static const struct i2c_algorithm sead3_platform_algo = { > + .master_xfer = sead3_pic32_platform_xfer, > + .functionality = sead3_pic32_platform_func, > +}; > + > +static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv) > +{ > + pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); > + pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR); > + pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET); > + pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL, > + priv->base + PIC32_I2CxSTATCLR); > +} > + > +static int sead3_i2c_platform_probe(struct platform_device *pdev) > +{ > + struct pic32_i2c_platform_data *priv; > + struct resource *r; > + int ret; > + > + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!r) { > + ret = -ENODEV; > + goto out; > + } > + > + priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL); > + if (!priv) { > + ret = -ENOMEM; > + goto out; > + } > + > + priv->base = r->start; OK. MIPS doesn't need ioremap? > + if (!priv->base) { > + ret = -EBUSY; > + goto out_mem; > + } > + > + priv->xfer_timeout = 200; > + priv->ack_timeout = 200; > + priv->ctl_timeout = 200; Why have three if they are all the same? > + > + priv->adap.nr = pdev->id; > + priv->adap.algo = &sead3_platform_algo; > + priv->adap.algo_data = priv; > + priv->adap.dev.parent = &pdev->dev; > + strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name)); > + > + sead3_i2c_platform_setup(priv); > + > + ret = i2c_add_numbered_adapter(&priv->adap); > + if (ret == 0) { > + platform_set_drvdata(pdev, priv); No, it must be set before! If I2C gets called after add_adapter and before the if, we have an OOPS. > + return 0; > + } > + > +out_mem: > + kfree(priv); > +out: > + return ret; > +} > + > +static int sead3_i2c_platform_remove(struct platform_device *pdev) > +{ > + struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); > + > + platform_set_drvdata(pdev, NULL); > + i2c_del_adapter(&priv->adap); > + kfree(priv); > + return 0; > +} > + > +#ifdef CONFIG_PM > +static int sead3_i2c_platform_suspend(struct platform_device *pdev, > + pm_message_t state) > +{ > + dev_dbg(&pdev->dev, "i2c_platform_disable\n"); > + return 0; > +} > + > +static int sead3_i2c_platform_resume(struct platform_device *pdev) > +{ > + struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); > + > + dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n"); > + sead3_i2c_platform_setup(priv); > + > + return 0; > +} > +#else > +#define sead3_i2c_platform_suspend NULL > +#define sead3_i2c_platform_resume NULL > +#endif > + > +static struct platform_driver sead3_i2c_platform_driver = { > + .driver = { > + .name = "sead3-i2c", > + .owner = THIS_MODULE, Not needed. > + }, > + .probe = sead3_i2c_platform_probe, > + .remove = sead3_i2c_platform_remove, > + .suspend = sead3_i2c_platform_suspend, > + .resume = sead3_i2c_platform_resume, > +}; > + > +static int __init sead3_i2c_platform_init(void) > +{ > + return platform_driver_register(&sead3_i2c_platform_driver); > +} > +module_init(sead3_i2c_platform_init); > + > +static void __exit sead3_i2c_platform_exit(void) > +{ > + platform_driver_unregister(&sead3_i2c_platform_driver); > +} > +module_exit(sead3_i2c_platform_exit); module_platform_driver() > + > +MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); > +MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver"); > +MODULE_LICENSE("GPL"); [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH] MIPS/I2C: Move SEAD3 I2C driver to where it belongs. @ 2014-11-13 8:24 ` Wolfram Sang 0 siblings, 0 replies; 20+ messages in thread From: Wolfram Sang @ 2014-11-13 8:24 UTC (permalink / raw) To: Ralf Baechle; +Cc: Markos Chandras, linux-i2c, linux-mips, Chris Dearman [-- Attachment #1: Type: text/plain, Size: 12993 bytes --] On Fri, Oct 24, 2014 at 02:26:57PM +0200, Ralf Baechle wrote: > Fixes the following build problem if CONFIG_I2C is disabled: > > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function 'i2c_platform_probe': > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:345:2: error: implicit declaration of > function 'i2c_add_numbered_adapter' [-Werror=implicit-function-declaration] > ret = i2c_add_numbered_adapter(&priv->adap); > ^ > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c: In function > 'i2c_platform_remove': > arch/mips/mti-sead3/sead3-pic32-i2c-drv.c:361:2: error: implicit declaration > of function 'i2c_del_adapter' [-Werror=implicit-function-declaration] > i2c_del_adapter(&priv->adap); > Uh, so this is already mainline? It has some issues. > Signed-off-by: Ralf Baechle <ralf@linux-mips.org> > Cc: Markos Chandras <markos.chandras@imgtec.com> > Cc: Wolfram Sang <wsa@the-dreams.de> > Cc: linux-i2c@vger.kernel.org > Cc: linux-mips@linux-mips.org > Cc: Chris Dearman <chris.dearman@imgtec.com> No diffstat? > diff --git a/drivers/i2c/busses/i2c-sead3.c b/drivers/i2c/busses/i2c-sead3.c > new file mode 100644 > index 0000000..1f787a6 > --- /dev/null > +++ b/drivers/i2c/busses/i2c-sead3.c > @@ -0,0 +1,405 @@ > +/* > + * This file is subject to the terms and conditions of the GNU General Public > + * License. See the file "COPYING" in the main directory of this archive > + * for more details. > + * > + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. > + */ > +#include <linux/init.h> > +#include <linux/module.h> > +#include <linux/slab.h> > +#include <linux/delay.h> > +#include <linux/i2c.h> > +#include <linux/platform_device.h> Please sort the includes. > + > +#define PIC32_I2CxCON 0x0000 > +#define PIC32_I2CCON_ON (1<<15) > +#define PIC32_I2CCON_ACKDT (1<<5) > +#define PIC32_I2CCON_ACKEN (1<<4) > +#define PIC32_I2CCON_RCEN (1<<3) > +#define PIC32_I2CCON_PEN (1<<2) > +#define PIC32_I2CCON_RSEN (1<<1) > +#define PIC32_I2CCON_SEN (1<<0) > +#define PIC32_I2CxCONCLR 0x0004 > +#define PIC32_I2CxCONSET 0x0008 > +#define PIC32_I2CxSTAT 0x0010 > +#define PIC32_I2CxSTATCLR 0x0014 > +#define PIC32_I2CSTAT_ACKSTAT (1<<15) > +#define PIC32_I2CSTAT_TRSTAT (1<<14) > +#define PIC32_I2CSTAT_BCL (1<<10) > +#define PIC32_I2CSTAT_IWCOL (1<<7) > +#define PIC32_I2CSTAT_I2COV (1<<6) > +#define PIC32_I2CxBRG 0x0040 > +#define PIC32_I2CxTRN 0x0050 > +#define PIC32_I2CxRCV 0x0060 > + > +static DEFINE_SPINLOCK(pic32_bus_lock); > + > +static void __iomem *bus_xfer = (void __iomem *)0xbf000600; > +static void __iomem *bus_status = (void __iomem *)0xbf000060; > + > +#define DELAY() udelay(100) > + > +static inline unsigned int ioready(void) > +{ > + return readl(bus_status) & 1; > +} > + > +static inline void wait_ioready(void) > +{ > + do { } while (!ioready()); > +} No timeout? > + > +static inline void wait_ioclear(void) > +{ > + do { } while (ioready()); > +} ditto > + > +static inline void check_ioclear(void) > +{ > + if (ioready()) { > + do { > + (void) readl(bus_xfer); > + DELAY(); > + } while (ioready()); > + } > +} > + > +static u32 pic32_bus_readl(u32 reg) > +{ > + unsigned long flags; > + u32 status, val; > + > + spin_lock_irqsave(&pic32_bus_lock, flags); > + > + check_ioclear(); > + writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer); Can we have names for all these magic hex-values? > + DELAY(); > + wait_ioready(); > + status = readl(bus_xfer); > + DELAY(); > + val = readl(bus_xfer); > + wait_ioclear(); > + > + spin_unlock_irqrestore(&pic32_bus_lock, flags); > + > + return val; > +} > + > +static void pic32_bus_writel(u32 val, u32 reg) > +{ > + unsigned long flags; > + u32 status; > + > + spin_lock_irqsave(&pic32_bus_lock, flags); > + > + check_ioclear(); > + writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer); > + DELAY(); > + writel(val, bus_xfer); > + DELAY(); > + wait_ioready(); > + status = readl(bus_xfer); > + wait_ioclear(); > + > + spin_unlock_irqrestore(&pic32_bus_lock, flags); > +} > + > +struct pic32_i2c_platform_data { > + u32 base; > + struct i2c_adapter adap; > + u32 xfer_timeout; > + u32 ack_timeout; > + u32 ctl_timeout; > +}; priv goes to the platform instead of the adapter? Unusual, why is that? > + > +static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET); > +} > + > +static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET); > +} > + > +static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR); > + pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); > +} > + > +static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET); > + pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET); > +} > + > +static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap) > +{ > + int i; > + > + for (i = 0; i < adap->ctl_timeout; i++) { > + if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) & > + (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN | > + PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN | > + PIC32_I2CCON_SEN)) == 0) && > + ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & > + (PIC32_I2CSTAT_TRSTAT)) == 0)) > + return 0; > + udelay(1); > + } > + return -ETIMEDOUT; > +} > + > +static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap, > + u32 byte) > +{ > + pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN); > + return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & > + PIC32_I2CSTAT_IWCOL; > +} > + > +static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap) > +{ > + pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET); > + while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN) > + ; > + pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR); > + return pic32_bus_readl(adap->base + PIC32_I2CxRCV); > +} > + > +static int pic32_i2c_address(struct pic32_i2c_platform_data *adap, > + unsigned int addr, int rd) > +{ > + pic32_i2c_idle(adap); > + pic32_i2c_start(adap); > + pic32_i2c_idle(adap); > + > + addr <<= 1; > + if (rd) > + addr |= 1; > + > + if (pic32_i2c_master_write(adap, addr)) > + return -EIO; > + pic32_i2c_idle(adap); > + if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & > + PIC32_I2CSTAT_ACKSTAT) > + return -EIO; I'd think this is -ENXIO. Please have a look at Documentation/i2c/fault-codes for the error codes we use. > + return 0; > +} > + > +static int sead3_i2c_read(struct pic32_i2c_platform_data *adap, > + unsigned char *buf, unsigned int len) > +{ > + u32 data; > + int i; > + > + i = 0; > + while (i < len) { > + data = pic32_i2c_master_read(adap); > + buf[i++] = data; > + if (i < len) > + pic32_i2c_ack(adap); > + else > + pic32_i2c_nack(adap); > + } > + > + pic32_i2c_stop(adap); > + pic32_i2c_idle(adap); > + return 0; > +} > + > +static int sead3_i2c_write(struct pic32_i2c_platform_data *adap, > + unsigned char *buf, unsigned int len) > +{ > + int i; > + u32 data; > + > + i = 0; > + while (i < len) { > + data = buf[i]; > + if (pic32_i2c_master_write(adap, data)) > + return -EIO; > + pic32_i2c_idle(adap); > + if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & > + PIC32_I2CSTAT_ACKSTAT) > + return -EIO; ditto > + i++; > + } > + > + pic32_i2c_stop(adap); > + pic32_i2c_idle(adap); > + return 0; > +} > + > +static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap, > + struct i2c_msg *msgs, int num) > +{ > + struct pic32_i2c_platform_data *adap = i2c_adap->algo_data; > + struct i2c_msg *p; > + int i, err = 0; > + > + for (i = 0; i < num; i++) { > +#define __BUFSIZE 80 > + int ii; > + static char buf[__BUFSIZE]; > + char *b = buf; > + > + p = &msgs[i]; > + b += sprintf(buf, " [%d bytes]", p->len); > + if ((p->flags & I2C_M_RD) == 0) { > + for (ii = 0; ii < p->len; ii++) { > + if (b < &buf[__BUFSIZE-4]) { > + b += sprintf(b, " %02x", p->buf[ii]); > + } else { > + strcat(b, "..."); > + break; > + } > + } > + } ??? Where is buf used? And we have other debugging options and support even tracing. Not needed. > + } > + > + for (i = 0; !err && i < num; i++) { > + p = &msgs[i]; > + err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD); > + if (err || !p->len) > + continue; So, you don't support SMBUS_QUICK? You should remove it from the functionality then. Or add support for it. > + if (p->flags & I2C_M_RD) > + err = sead3_i2c_read(adap, p->buf, p->len); > + else > + err = sead3_i2c_write(adap, p->buf, p->len); > + } > + > + /* Return the number of messages processed, or the error code. */ > + if (err == 0) > + err = num; > + > + return err; > +} > + > +static u32 sead3_pic32_platform_func(struct i2c_adapter *adap) > +{ > + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; > +} > + > +static const struct i2c_algorithm sead3_platform_algo = { > + .master_xfer = sead3_pic32_platform_xfer, > + .functionality = sead3_pic32_platform_func, > +}; > + > +static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv) > +{ > + pic32_bus_writel(500, priv->base + PIC32_I2CxBRG); > + pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR); > + pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET); > + pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL, > + priv->base + PIC32_I2CxSTATCLR); > +} > + > +static int sead3_i2c_platform_probe(struct platform_device *pdev) > +{ > + struct pic32_i2c_platform_data *priv; > + struct resource *r; > + int ret; > + > + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!r) { > + ret = -ENODEV; > + goto out; > + } > + > + priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL); > + if (!priv) { > + ret = -ENOMEM; > + goto out; > + } > + > + priv->base = r->start; OK. MIPS doesn't need ioremap? > + if (!priv->base) { > + ret = -EBUSY; > + goto out_mem; > + } > + > + priv->xfer_timeout = 200; > + priv->ack_timeout = 200; > + priv->ctl_timeout = 200; Why have three if they are all the same? > + > + priv->adap.nr = pdev->id; > + priv->adap.algo = &sead3_platform_algo; > + priv->adap.algo_data = priv; > + priv->adap.dev.parent = &pdev->dev; > + strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name)); > + > + sead3_i2c_platform_setup(priv); > + > + ret = i2c_add_numbered_adapter(&priv->adap); > + if (ret == 0) { > + platform_set_drvdata(pdev, priv); No, it must be set before! If I2C gets called after add_adapter and before the if, we have an OOPS. > + return 0; > + } > + > +out_mem: > + kfree(priv); > +out: > + return ret; > +} > + > +static int sead3_i2c_platform_remove(struct platform_device *pdev) > +{ > + struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); > + > + platform_set_drvdata(pdev, NULL); > + i2c_del_adapter(&priv->adap); > + kfree(priv); > + return 0; > +} > + > +#ifdef CONFIG_PM > +static int sead3_i2c_platform_suspend(struct platform_device *pdev, > + pm_message_t state) > +{ > + dev_dbg(&pdev->dev, "i2c_platform_disable\n"); > + return 0; > +} > + > +static int sead3_i2c_platform_resume(struct platform_device *pdev) > +{ > + struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev); > + > + dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n"); > + sead3_i2c_platform_setup(priv); > + > + return 0; > +} > +#else > +#define sead3_i2c_platform_suspend NULL > +#define sead3_i2c_platform_resume NULL > +#endif > + > +static struct platform_driver sead3_i2c_platform_driver = { > + .driver = { > + .name = "sead3-i2c", > + .owner = THIS_MODULE, Not needed. > + }, > + .probe = sead3_i2c_platform_probe, > + .remove = sead3_i2c_platform_remove, > + .suspend = sead3_i2c_platform_suspend, > + .resume = sead3_i2c_platform_resume, > +}; > + > +static int __init sead3_i2c_platform_init(void) > +{ > + return platform_driver_register(&sead3_i2c_platform_driver); > +} > +module_init(sead3_i2c_platform_init); > + > +static void __exit sead3_i2c_platform_exit(void) > +{ > + platform_driver_unregister(&sead3_i2c_platform_driver); > +} > +module_exit(sead3_i2c_platform_exit); module_platform_driver() > + > +MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); > +MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver"); > +MODULE_LICENSE("GPL"); [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 3/3] MIPS: sead3: Only build the led driver if LEDS_CLASS is enabled @ 2014-10-09 9:34 ` Markos Chandras 0 siblings, 0 replies; 20+ messages in thread From: Markos Chandras @ 2014-10-09 9:34 UTC (permalink / raw) To: linux-mips; +Cc: Markos Chandras Fixes the following randconfig problem leds-sead3.c:(.text+0x7dc): undefined reference to `led_classdev_unregister' leds-sead3.c:(.text+0x7e8): undefined reference to `led_classdev_unregister' Reviewed-by: Steven J. Hill <Steven.Hill@imgtec.com> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> --- arch/mips/mti-sead3/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index a632b9cfe526..10093fc9ebc9 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -13,11 +13,10 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ sead3-platform.o sead3-reset.o \ sead3-setup.o sead3-time.o -obj-y += leds-sead3.o sead3-leds.o - obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o obj-$(CONFIG_I2C) += sead3-i2c.o sead3-i2c-dev.o \ sead3-pic32-bus.o lsead3-pic32-i2c-drv.o +obj-$(LEDS_CLASS) += leds-sead3.o sead3-leds.o obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o obj-$(CONFIG_OF) += sead3.dtb.o -- 2.1.2 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 3/3] MIPS: sead3: Only build the led driver if LEDS_CLASS is enabled @ 2014-10-09 9:34 ` Markos Chandras 0 siblings, 0 replies; 20+ messages in thread From: Markos Chandras @ 2014-10-09 9:34 UTC (permalink / raw) To: linux-mips; +Cc: Markos Chandras Fixes the following randconfig problem leds-sead3.c:(.text+0x7dc): undefined reference to `led_classdev_unregister' leds-sead3.c:(.text+0x7e8): undefined reference to `led_classdev_unregister' Reviewed-by: Steven J. Hill <Steven.Hill@imgtec.com> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> --- arch/mips/mti-sead3/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index a632b9cfe526..10093fc9ebc9 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -13,11 +13,10 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ sead3-platform.o sead3-reset.o \ sead3-setup.o sead3-time.o -obj-y += leds-sead3.o sead3-leds.o - obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o obj-$(CONFIG_I2C) += sead3-i2c.o sead3-i2c-dev.o \ sead3-pic32-bus.o lsead3-pic32-i2c-drv.o +obj-$(LEDS_CLASS) += leds-sead3.o sead3-leds.o obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o obj-$(CONFIG_OF) += sead3.dtb.o -- 2.1.2 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 3/3] MIPS: sead3: Only build the led driver if LEDS_CLASS is enabled 2014-10-09 9:34 ` Markos Chandras (?) @ 2014-10-23 23:54 ` Ralf Baechle 2014-10-23 22:41 ` [PATCH 1/3] MIPS: SEAD3: Fix LED device registration Ralf Baechle ` (2 more replies) -1 siblings, 3 replies; 20+ messages in thread From: Ralf Baechle @ 2014-10-23 23:54 UTC (permalink / raw) To: Markos Chandras; +Cc: linux-mips On Thu, Oct 09, 2014 at 10:34:21AM +0100, Markos Chandras wrote: > leds-sead3.c:(.text+0x7dc): undefined reference to `led_classdev_unregister' > leds-sead3.c:(.text+0x7e8): undefined reference to `led_classdev_unregister' > > Reviewed-by: Steven J. Hill <Steven.Hill@imgtec.com> > Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> Hmm... I think there's a whole lot more broken. Let's start with the Makefile: -obj-y += leds-sead3.o sead3-leds.o Very creative filenames. No way to know in what way foo-bar and bar-foo are different. But let's take a look at sead3-leds: [...] module_init(led_init); MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("LED probe driver for SEAD-3"); But although you were trying to make this a module, this better shouldn't be one, the devices should always be registered if they're there, driver enabled or not. Anyway this should probably become a device_initcall() and all the module bits should go. And now let's take a look at sead3-led.. oh wait, that's leds-sead3 - did I bitch about the filename before? That's a complete device driver and it blows up primarily because it lives in a directory where it shouldn't be at all. Ralf ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 1/3] MIPS: SEAD3: Fix LED device registration. 2014-10-23 23:54 ` Ralf Baechle @ 2014-10-23 22:41 ` Ralf Baechle 2014-10-23 23:32 ` [PATCH 2/3] MIPS: SEAD3: Collect LED platform device registration in a single file Ralf Baechle 2014-10-23 23:50 ` [PATCH 3/3] LED/MIPS: Move SEAD3 LED driver to where it belongs Ralf Baechle 2 siblings, 0 replies; 20+ messages in thread From: Ralf Baechle @ 2014-10-23 22:41 UTC (permalink / raw) To: Markos Chandras, linux-mips, Bryan Wu, Richard Purdie, linux-leds This isn't a module and shouldn't be one. Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/mti-sead3/sead3-leds.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/arch/mips/mti-sead3/sead3-leds.c b/arch/mips/mti-sead3/sead3-leds.c index 20102a6..c427c57 100644 --- a/arch/mips/mti-sead3/sead3-leds.c +++ b/arch/mips/mti-sead3/sead3-leds.c @@ -5,7 +5,7 @@ * * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. */ -#include <linux/module.h> +#include <linux/init.h> #include <linux/leds.h> #include <linux/platform_device.h> @@ -76,8 +76,4 @@ static int __init led_init(void) return platform_device_register(&fled_device); } -module_init(led_init); - -MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("LED probe driver for SEAD-3"); +device_initcall(led_init); -- 1.9.3 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 2/3] MIPS: SEAD3: Collect LED platform device registration in a single file. 2014-10-23 23:54 ` Ralf Baechle 2014-10-23 22:41 ` [PATCH 1/3] MIPS: SEAD3: Fix LED device registration Ralf Baechle @ 2014-10-23 23:32 ` Ralf Baechle 2014-10-23 23:50 ` [PATCH 3/3] LED/MIPS: Move SEAD3 LED driver to where it belongs Ralf Baechle 2 siblings, 0 replies; 20+ messages in thread From: Ralf Baechle @ 2014-10-23 23:32 UTC (permalink / raw) To: Markos Chandras, linux-mips, Bryan Wu, Richard Purdie, linux-leds Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/mti-sead3/leds-sead3.c | 19 +------------------ arch/mips/mti-sead3/sead3-leds.c | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c index 0a168c9..e5632e6 100644 --- a/arch/mips/mti-sead3/leds-sead3.c +++ b/arch/mips/mti-sead3/leds-sead3.c @@ -15,8 +15,6 @@ #define DRVNAME "sead3-led" -static struct platform_device *pdev; - static void sead3_pled_set(struct led_classdev *led_cdev, enum led_brightness value) { @@ -76,26 +74,11 @@ static struct platform_driver sead3_led_driver = { static int __init sead3_led_init(void) { - int ret; - - ret = platform_driver_register(&sead3_led_driver); - if (ret < 0) - goto out; - - pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); - if (IS_ERR(pdev)) { - ret = PTR_ERR(pdev); - platform_driver_unregister(&sead3_led_driver); - goto out; - } - -out: - return ret; + return platform_driver_register(&sead3_led_driver); } static void __exit sead3_led_exit(void) { - platform_device_unregister(pdev); platform_driver_unregister(&sead3_led_driver); } diff --git a/arch/mips/mti-sead3/sead3-leds.c b/arch/mips/mti-sead3/sead3-leds.c index c427c57..c6fa3e4 100644 --- a/arch/mips/mti-sead3/sead3-leds.c +++ b/arch/mips/mti-sead3/sead3-leds.c @@ -70,10 +70,20 @@ static struct platform_device fled_device = { .resource = fled_resources }; -static int __init led_init(void) +static struct platform_device sead3_led_device = { + .name = "sead3-led", + .id = -1, +}; + +struct platform_device *sead3_led_devices[] = { + &pled_device, + &fled_device, + &sead3_led_device, +}; + +static int __init sead3_led_init(void) { - platform_device_register(&pled_device); - return platform_device_register(&fled_device); + return platform_add_devices(sead3_led_devices, ARRAY_SIZE(sead3_led_devices)); } -device_initcall(led_init); +device_initcall(sead3_led_init); -- 1.9.3 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 3/3] LED/MIPS: Move SEAD3 LED driver to where it belongs. 2014-10-23 23:54 ` Ralf Baechle 2014-10-23 22:41 ` [PATCH 1/3] MIPS: SEAD3: Fix LED device registration Ralf Baechle 2014-10-23 23:32 ` [PATCH 2/3] MIPS: SEAD3: Collect LED platform device registration in a single file Ralf Baechle @ 2014-10-23 23:50 ` Ralf Baechle 2014-10-24 23:19 ` Bryan Wu 2 siblings, 1 reply; 20+ messages in thread From: Ralf Baechle @ 2014-10-23 23:50 UTC (permalink / raw) To: Markos Chandras, linux-mips, Bryan Wu, Richard Purdie, linux-leds Fixes the following randconfig problem leds-sead3.c:(.text+0x7dc): undefined reference to `led_classdev_unregister' leds-sead3.c:(.text+0x7e8): undefined reference to `led_classdev_unregister' Signed-off-by: Ralf Baechle <ralf@linux-mips.org> --- arch/mips/mti-sead3/Makefile | 2 +- arch/mips/mti-sead3/leds-sead3.c | 90 ---------------------------------------- drivers/leds/Kconfig | 9 ++++ drivers/leds/Makefile | 1 + drivers/leds/leds-sead3.c | 90 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 91 deletions(-) delete mode 100644 arch/mips/mti-sead3/leds-sead3.c create mode 100644 drivers/leds/leds-sead3.c diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile index febf433..aa8a857 100644 --- a/arch/mips/mti-sead3/Makefile +++ b/arch/mips/mti-sead3/Makefile @@ -15,7 +15,7 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ obj-y += sead3-i2c-dev.o sead3-i2c.o \ sead3-pic32-i2c-drv.o sead3-pic32-bus.o \ - leds-sead3.o sead3-leds.o + sead3-leds.o obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c deleted file mode 100644 index e5632e6..0000000 --- a/arch/mips/mti-sead3/leds-sead3.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/leds.h> -#include <linux/err.h> -#include <linux/io.h> - -#define DRVNAME "sead3-led" - -static void sead3_pled_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - pr_debug("sead3_pled_set\n"); - writel(value, (void __iomem *)0xBF000210); /* FIXME */ -} - -static void sead3_fled_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - pr_debug("sead3_fled_set\n"); - writel(value, (void __iomem *)0xBF000218); /* FIXME */ -} - -static struct led_classdev sead3_pled = { - .name = "sead3::pled", - .brightness_set = sead3_pled_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static struct led_classdev sead3_fled = { - .name = "sead3::fled", - .brightness_set = sead3_fled_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static int sead3_led_probe(struct platform_device *pdev) -{ - int ret; - - ret = led_classdev_register(&pdev->dev, &sead3_pled); - if (ret < 0) - return ret; - - ret = led_classdev_register(&pdev->dev, &sead3_fled); - if (ret < 0) - led_classdev_unregister(&sead3_pled); - - return ret; -} - -static int sead3_led_remove(struct platform_device *pdev) -{ - led_classdev_unregister(&sead3_pled); - led_classdev_unregister(&sead3_fled); - return 0; -} - -static struct platform_driver sead3_led_driver = { - .probe = sead3_led_probe, - .remove = sead3_led_remove, - .driver = { - .name = DRVNAME, - .owner = THIS_MODULE, - }, -}; - -static int __init sead3_led_init(void) -{ - return platform_driver_register(&sead3_led_driver); -} - -static void __exit sead3_led_exit(void) -{ - platform_driver_unregister(&sead3_led_driver); -} - -module_init(sead3_led_init); -module_exit(sead3_led_exit); - -MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>"); -MODULE_DESCRIPTION("SEAD3 LED driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index a210338..b86aa85 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -477,6 +477,15 @@ config LEDS_MENF21BMC This driver can also be built as a module. If so the module will be called leds-menf21bmc. +config LEDS_SEAD3 + tristate "LED support for the MIPS SEAD 3 board" + depends on LEDS_CLASS && MIPS_SEAD3 + help + Say Y here to include support for the MEN 14F021P00 BMC LEDs. + + This driver can also be built as a module. If so the module + will be called leds-sead3. + comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)" config LEDS_BLINKM diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index a2b1647..4f22241 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o +obj-$(CONFIG_LEDS_SEAD3) += leds-sead3.o # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/drivers/leds/leds-sead3.c b/drivers/leds/leds-sead3.c new file mode 100644 index 0000000..0cf79f5 --- /dev/null +++ b/drivers/leds/leds-sead3.c @@ -0,0 +1,90 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/leds.h> +#include <linux/err.h> +#include <linux/io.h> + +static void sead3_pled_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + pr_debug("sead3_pled_set\n"); + writel(value, (void __iomem *)0xBF000210); /* FIXME */ +} + +static void sead3_fled_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + pr_debug("sead3_fled_set\n"); + writel(value, (void __iomem *)0xBF000218); /* FIXME */ +} + +static struct led_classdev sead3_pled = { + .name = "sead3::pled", + .brightness_set = sead3_pled_set, + .flags = LED_CORE_SUSPENDRESUME, +}; + +static struct led_classdev sead3_fled = { + .name = "sead3::fled", + .brightness_set = sead3_fled_set, + .flags = LED_CORE_SUSPENDRESUME, +}; + +static int sead3_led_probe(struct platform_device *pdev) +{ + int ret; + + ret = led_classdev_register(&pdev->dev, &sead3_pled); + if (ret < 0) + return ret; + + ret = led_classdev_register(&pdev->dev, &sead3_fled); + if (ret < 0) + led_classdev_unregister(&sead3_pled); + + return ret; +} + +static int sead3_led_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&sead3_pled); + led_classdev_unregister(&sead3_fled); + + return 0; +} + +static struct platform_driver sead3_led_driver = { + .probe = sead3_led_probe, + .remove = sead3_led_remove, + .driver = { + .name = "sead3-led", + .owner = THIS_MODULE, + }, +}; + +static int __init sead3_led_init(void) +{ + return platform_driver_register(&sead3_led_driver); +} + +static void __exit sead3_led_exit(void) +{ + platform_driver_unregister(&sead3_led_driver); +} + +module_init(sead3_led_init); +module_exit(sead3_led_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SEAD3 LED driver"); +MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>"); +MODULE_ALIAS("platform:sead3-led"); -- 1.9.3 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 3/3] LED/MIPS: Move SEAD3 LED driver to where it belongs. 2014-10-23 23:50 ` [PATCH 3/3] LED/MIPS: Move SEAD3 LED driver to where it belongs Ralf Baechle @ 2014-10-24 23:19 ` Bryan Wu 0 siblings, 0 replies; 20+ messages in thread From: Bryan Wu @ 2014-10-24 23:19 UTC (permalink / raw) To: Ralf Baechle Cc: Markos Chandras, linux-mips, Richard Purdie, Linux LED Subsystem On Thu, Oct 23, 2014 at 4:50 PM, Ralf Baechle <ralf@linux-mips.org> wrote: > Fixes the following randconfig problem > > leds-sead3.c:(.text+0x7dc): undefined reference to `led_classdev_unregister' > leds-sead3.c:(.text+0x7e8): undefined reference to `led_classdev_unregister' > I think you can fold these 3 patches into one patch then. > Signed-off-by: Ralf Baechle <ralf@linux-mips.org> > --- > arch/mips/mti-sead3/Makefile | 2 +- > arch/mips/mti-sead3/leds-sead3.c | 90 ---------------------------------------- > drivers/leds/Kconfig | 9 ++++ > drivers/leds/Makefile | 1 + > drivers/leds/leds-sead3.c | 90 ++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 101 insertions(+), 91 deletions(-) > delete mode 100644 arch/mips/mti-sead3/leds-sead3.c > create mode 100644 drivers/leds/leds-sead3.c > > diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile > index febf433..aa8a857 100644 > --- a/arch/mips/mti-sead3/Makefile > +++ b/arch/mips/mti-sead3/Makefile > @@ -15,7 +15,7 @@ obj-y := sead3-lcd.o sead3-display.o sead3-init.o \ > > obj-y += sead3-i2c-dev.o sead3-i2c.o \ > sead3-pic32-i2c-drv.o sead3-pic32-bus.o \ > - leds-sead3.o sead3-leds.o > + sead3-leds.o > > obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o > obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o > diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c > deleted file mode 100644 > index e5632e6..0000000 > --- a/arch/mips/mti-sead3/leds-sead3.c > +++ /dev/null > @@ -1,90 +0,0 @@ > -/* > - * This file is subject to the terms and conditions of the GNU General Public > - * License. See the file "COPYING" in the main directory of this archive > - * for more details. > - * > - * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. > - */ > -#include <linux/kernel.h> > -#include <linux/module.h> > -#include <linux/init.h> > -#include <linux/platform_device.h> > -#include <linux/leds.h> > -#include <linux/err.h> > -#include <linux/io.h> > - > -#define DRVNAME "sead3-led" > - > -static void sead3_pled_set(struct led_classdev *led_cdev, > - enum led_brightness value) > -{ > - pr_debug("sead3_pled_set\n"); > - writel(value, (void __iomem *)0xBF000210); /* FIXME */ > -} > - > -static void sead3_fled_set(struct led_classdev *led_cdev, > - enum led_brightness value) > -{ > - pr_debug("sead3_fled_set\n"); > - writel(value, (void __iomem *)0xBF000218); /* FIXME */ > -} > - > -static struct led_classdev sead3_pled = { > - .name = "sead3::pled", > - .brightness_set = sead3_pled_set, > - .flags = LED_CORE_SUSPENDRESUME, > -}; > - > -static struct led_classdev sead3_fled = { > - .name = "sead3::fled", > - .brightness_set = sead3_fled_set, > - .flags = LED_CORE_SUSPENDRESUME, > -}; > - > -static int sead3_led_probe(struct platform_device *pdev) > -{ > - int ret; > - > - ret = led_classdev_register(&pdev->dev, &sead3_pled); > - if (ret < 0) > - return ret; > - > - ret = led_classdev_register(&pdev->dev, &sead3_fled); > - if (ret < 0) > - led_classdev_unregister(&sead3_pled); > - > - return ret; > -} > - > -static int sead3_led_remove(struct platform_device *pdev) > -{ > - led_classdev_unregister(&sead3_pled); > - led_classdev_unregister(&sead3_fled); > - return 0; > -} > - > -static struct platform_driver sead3_led_driver = { > - .probe = sead3_led_probe, > - .remove = sead3_led_remove, > - .driver = { > - .name = DRVNAME, > - .owner = THIS_MODULE, > - }, > -}; > - > -static int __init sead3_led_init(void) > -{ > - return platform_driver_register(&sead3_led_driver); > -} > - > -static void __exit sead3_led_exit(void) > -{ > - platform_driver_unregister(&sead3_led_driver); > -} > - > -module_init(sead3_led_init); > -module_exit(sead3_led_exit); > - > -MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>"); > -MODULE_DESCRIPTION("SEAD3 LED driver"); > -MODULE_LICENSE("GPL"); > diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig > index a210338..b86aa85 100644 > --- a/drivers/leds/Kconfig > +++ b/drivers/leds/Kconfig > @@ -477,6 +477,15 @@ config LEDS_MENF21BMC > This driver can also be built as a module. If so the module > will be called leds-menf21bmc. > > +config LEDS_SEAD3 > + tristate "LED support for the MIPS SEAD 3 board" > + depends on LEDS_CLASS && MIPS_SEAD3 > + help > + Say Y here to include support for the MEN 14F021P00 BMC LEDs. > + Is this driver similar to drivers/leds/leds-menf21bmc.c? If we can reuse the code it should be better. > + This driver can also be built as a module. If so the module > + will be called leds-sead3. > + > comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)" > > config LEDS_BLINKM > diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile > index a2b1647..4f22241 100644 > --- a/drivers/leds/Makefile > +++ b/drivers/leds/Makefile > @@ -56,6 +56,7 @@ obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o > obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o > obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o > obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o > +obj-$(CONFIG_LEDS_SEAD3) += leds-sead3.o > > # LED SPI Drivers > obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o > diff --git a/drivers/leds/leds-sead3.c b/drivers/leds/leds-sead3.c > new file mode 100644 > index 0000000..0cf79f5 > --- /dev/null > +++ b/drivers/leds/leds-sead3.c > @@ -0,0 +1,90 @@ > +/* > + * This file is subject to the terms and conditions of the GNU General Public > + * License. See the file "COPYING" in the main directory of this archive > + * for more details. > + * > + * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. > + */ > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/init.h> > +#include <linux/platform_device.h> > +#include <linux/leds.h> > +#include <linux/err.h> > +#include <linux/io.h> > + Please reorder this list in alphabetic order. > +static void sead3_pled_set(struct led_classdev *led_cdev, > + enum led_brightness value) > +{ > + pr_debug("sead3_pled_set\n"); Don't use pr_debug, please use dev_dbg(); > + writel(value, (void __iomem *)0xBF000210); /* FIXME */ Fix this, define some meaningful name of the address. > +} > + > +static void sead3_fled_set(struct led_classdev *led_cdev, > + enum led_brightness value) > +{ > + pr_debug("sead3_fled_set\n"); Don't use pr_debug, please use dev_dbg(); > + writel(value, (void __iomem *)0xBF000218); /* FIXME */ ditto > +} > + > +static struct led_classdev sead3_pled = { > + .name = "sead3::pled", > + .brightness_set = sead3_pled_set, > + .flags = LED_CORE_SUSPENDRESUME, > +}; > + > +static struct led_classdev sead3_fled = { > + .name = "sead3::fled", > + .brightness_set = sead3_fled_set, > + .flags = LED_CORE_SUSPENDRESUME, > +}; > + What's pled and fled? Please give more meaningful name or document it. > +static int sead3_led_probe(struct platform_device *pdev) > +{ > + int ret; > + > + ret = led_classdev_register(&pdev->dev, &sead3_pled); > + if (ret < 0) > + return ret; > + > + ret = led_classdev_register(&pdev->dev, &sead3_fled); > + if (ret < 0) > + led_classdev_unregister(&sead3_pled); > + > + return ret; > +} > + > +static int sead3_led_remove(struct platform_device *pdev) > +{ > + led_classdev_unregister(&sead3_pled); > + led_classdev_unregister(&sead3_fled); > + > + return 0; > +} > + > +static struct platform_driver sead3_led_driver = { > + .probe = sead3_led_probe, > + .remove = sead3_led_remove, > + .driver = { > + .name = "sead3-led", > + .owner = THIS_MODULE, > + }, > +}; > + > +static int __init sead3_led_init(void) > +{ > + return platform_driver_register(&sead3_led_driver); > +} > + > +static void __exit sead3_led_exit(void) > +{ > + platform_driver_unregister(&sead3_led_driver); > +} > + > +module_init(sead3_led_init); > +module_exit(sead3_led_exit); > + You can use module_platform_driver() here. > +MODULE_LICENSE("GPL"); > +MODULE_DESCRIPTION("SEAD3 LED driver"); > +MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>"); > +MODULE_ALIAS("platform:sead3-led"); > -- > 1.9.3 > ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2014-11-13 8:24 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-09 9:34 [PATCH 0/3] Malta/SEAD3 kernel image size patches for 3.18 Markos Chandras
2014-10-09 9:34 ` Markos Chandras
2014-10-09 9:34 ` [PATCH 1/3] MIPS: Malta: Do not build the malta-amon.c file if CMP is not enabled Markos Chandras
2014-10-09 9:34 ` Markos Chandras
2014-10-09 9:34 ` [PATCH 2/3] MIPS: sead3: Build the I2C related devices if CONFIG_I2C is enabled Markos Chandras
2014-10-09 9:34 ` Markos Chandras
2014-10-23 18:19 ` Ralf Baechle
2014-10-24 8:15 ` Ralf Baechle
2014-10-24 10:06 ` [PATCH] MIPS: SEAD3: Nuke unused sead3-pic32-i2c-drv Ralf Baechle
[not found] ` <20141023181925.GA6719-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>
2014-10-24 12:26 ` [PATCH] MIPS/I2C: Move SEAD3 I2C driver to where it belongs Ralf Baechle
2014-10-24 12:26 ` Ralf Baechle
[not found] ` <20141024122656.GC12641-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>
2014-11-13 8:24 ` Wolfram Sang
2014-11-13 8:24 ` Wolfram Sang
2014-10-09 9:34 ` [PATCH 3/3] MIPS: sead3: Only build the led driver if LEDS_CLASS is enabled Markos Chandras
2014-10-09 9:34 ` Markos Chandras
2014-10-23 23:54 ` Ralf Baechle
2014-10-23 22:41 ` [PATCH 1/3] MIPS: SEAD3: Fix LED device registration Ralf Baechle
2014-10-23 23:32 ` [PATCH 2/3] MIPS: SEAD3: Collect LED platform device registration in a single file Ralf Baechle
2014-10-23 23:50 ` [PATCH 3/3] LED/MIPS: Move SEAD3 LED driver to where it belongs Ralf Baechle
2014-10-24 23:19 ` Bryan Wu
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.