[RFC PATCH] s5pv210: New samsung SoCs devices support

Kyungmin Park kmpark at infradead.org
Fri Jul 30 05:52:02 EDT 2010


To Ben,

Any comments?

On Mon, Jul 19, 2010 at 4:33 PM, Kyungmin Park <kmpark at infradead.org> wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
>
> Now only one samsung SoC and its devices are supported in mainline and
> can't support several SoCs simultaneously since each SoCs has different memory
> address and different number of IPs.
> e.g., some 64xx series has 2 I2Cs devices. C1xx series have three I2Cs and
> new SoC, S5PV310 has eight I2Cs.
>
> To address these issues. Each devices of SoC are registered at each devices tress (or list) and use it when probe time.
>
> Of course fundamentally we can't compile several SoCs simultaneously at current state. It's just preparation for supporting it
>
> Any comments are welcome.
>
> Thank you,
> Kyungmin Park
>
> Here's test codes and results.
>
> static struct samsung_device goni_samsung_devices[] = {
>        /* device, index */
>       S5PV210_DEVICE_ID(I2C, 0),
>       S5PV210_DEVICE_ID(I2C, 1),
>       S5PV210_DEVICE_ID(I2C, 2),
> };
>
> static void __init goni_machine_init(void)
> {
>       samsung_platform_add_devices(goni_samsung_devices,
>                                       ARRAY_SIZE(goni_samsung_devices));
>       platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices));
>  }
>
> [    0.140000] samsung 0 device type 0, name s3c2440-i2c, id 2
> [    0.145000] samsung 0 device type 0, name s3c2440-i2c, id 1
> [    0.150000] samsung 0 device type 0, name s3c2440-i2c, id 0
> [    0.155000] S5PV210: Initializing architecture
> [    0.165000] bio: create slab <bio-0> at 0
> [    0.165000] s3c-i2c s3c2440-i2c.0: slave address 0x10
> [    0.170000] s3c-i2c s3c2440-i2c.0: bus frequency set to 378 KHz
> [    0.175000] s3c-i2c s3c2440-i2c.0: i2c-0: S3C I2C adapter
> [    0.185000] s3c-i2c s3c2440-i2c.1: slave address 0x10
> [    0.190000] s3c-i2c s3c2440-i2c.1: bus frequency set to 378 KHz
> [    0.195000] s3c-i2c s3c2440-i2c.1: i2c-1: S3C I2C adapter
> [    0.200000] s3c-i2c s3c2440-i2c.2: slave address 0x10
> [    0.205000] s3c-i2c s3c2440-i2c.2: bus frequency set to 378 KHz
> [    0.210000] s3c-i2c s3c2440-i2c.2: i2c-2: S3C I2C adapter
>
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> ---
>  mach-s5pv210/Makefile                      |    1
>  mach-s5pv210/devices.c                     |  144 +++++++++++++++++++++++++++++
>  mach-s5pv210/include/mach/irqs.h           |    5 -
>  plat-samsung/Makefile                      |    1
>  plat-samsung/devices.c                     |  102 ++++++++++++++++++++
>  plat-samsung/include/plat/samsung_device.h |   53 ++++++++++
>  6 files changed, 305 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
> index 30be9a6..33ca7eb 100644
> --- a/arch/arm/mach-s5pv210/Makefile
> +++ b/arch/arm/mach-s5pv210/Makefile
> @@ -24,6 +24,7 @@ obj-$(CONFIG_MACH_GONI)               += mach-goni.o
>
>  # device support
>
> +obj-y                          += devices.o
>  obj-y                          += dev-audio.o
>  obj-$(CONFIG_S3C64XX_DEV_SPI)  += dev-spi.o
>  obj-$(CONFIG_S5PC110_DEV_ONENAND) += dev-onenand.o
> diff --git a/arch/arm/mach-s5pv210/devices.c b/arch/arm/mach-s5pv210/devices.c
> new file mode 100644
> index 0000000..baf6567
> --- /dev/null
> +++ b/arch/arm/mach-s5pv210/devices.c
> @@ -0,0 +1,144 @@
> +/*
> + * arch/arm/mach-s5pv210/devices.c
> + *
> + *  Copyright 2010 Samsung Electronics
> + *  Kyungmin Park <kyungmin.park at samsung.com>
> + *
> + * Sasmung S5PC110/S5PV210 devices definitions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/platform_device.h>
> +#include <linux/gpio.h>
> +#include <linux/irq.h>
> +
> +#include <mach/map.h>
> +#include <plat/gpio-cfg.h>
> +#include <plat/samsung_device.h>
> +#include <plat/iic.h>
> +
> +static struct resource s5pv210_i2c0_resource[] = {
> +       [0] = {
> +               .start = S5PV210_PA_IIC0,
> +               .end   = S5PV210_PA_IIC0 + SZ_4K - 1,
> +               .flags = IORESOURCE_MEM,
> +       },
> +       [1] = {
> +               .start = S5PV210_IRQ_I2C0,
> +               .end   = S5PV210_IRQ_I2C0,
> +               .flags = IORESOURCE_IRQ,
> +       },
> +};
> +
> +static void s5pv210_i2c0_cfg_gpio(struct platform_device *dev)
> +{
> +       s3c_gpio_cfgpin(S5PV210_GPD1(0), S3C_GPIO_SFN(2));
> +       s3c_gpio_setpull(S5PV210_GPD1(0), S3C_GPIO_PULL_UP);
> +       s3c_gpio_cfgpin(S5PV210_GPD1(1), S3C_GPIO_SFN(2));
> +       s3c_gpio_setpull(S5PV210_GPD1(1), S3C_GPIO_PULL_UP);
> +}
> +
> +static struct s3c2410_platform_i2c s5pv210_i2c0_data = {
> +       .bus_num                = 0,
> +       .slave_addr             = 0x10,
> +       .frequency              = 400*1000,
> +       .sda_delay              = 100,
> +       .cfg_gpio               = s5pv210_i2c0_cfg_gpio,
> +};
> +
> +static struct platform_device s5pv210_i2c0_device = {
> +       .name                   = "s3c2440-i2c",
> +       .id                     = 0,
> +       .dev                    = {
> +               .platform_data  = &s5pv210_i2c0_data,
> +       },
> +       .num_resources          = ARRAY_SIZE(s5pv210_i2c0_resource),
> +       .resource               = s5pv210_i2c0_resource,
> +};
> +
> +SAMSUNG_DEVICE_INIT(SAMSUNG_S5PV210, SAMSUNG_DEVICE_I2C, s5pv210_i2c0_device);
> +
> +static struct resource s5pv210_i2c1_resource[] = {
> +       [0] = {
> +               .start = S5PV210_PA_IIC1,
> +               .end   = S5PV210_PA_IIC1 + SZ_4K - 1,
> +               .flags = IORESOURCE_MEM,
> +       },
> +       [1] = {
> +               .start = S5PV210_IRQ_I2C1,
> +               .end   = S5PV210_IRQ_I2C1,
> +               .flags = IORESOURCE_IRQ,
> +       },
> +};
> +
> +static void s5pv210_i2c1_cfg_gpio(struct platform_device *dev)
> +{
> +       s3c_gpio_cfgpin(S5PV210_GPD1(2), S3C_GPIO_SFN(2));
> +       s3c_gpio_setpull(S5PV210_GPD1(2), S3C_GPIO_PULL_UP);
> +       s3c_gpio_cfgpin(S5PV210_GPD1(3), S3C_GPIO_SFN(2));
> +       s3c_gpio_setpull(S5PV210_GPD1(3), S3C_GPIO_PULL_UP);
> +}
> +
> +static struct s3c2410_platform_i2c s5pv210_i2c1_data = {
> +       .bus_num                = 1,
> +       .slave_addr             = 0x10,
> +       .frequency              = 400*1000,
> +       .sda_delay              = 100,
> +       .cfg_gpio               = s5pv210_i2c1_cfg_gpio,
> +};
> +
> +static struct platform_device s5pv210_i2c1_device = {
> +       .name                   = "s3c2440-i2c",
> +       .id                     = 1,
> +       .dev                    = {
> +               .platform_data  = &s5pv210_i2c1_data,
> +       },
> +       .num_resources          = ARRAY_SIZE(s5pv210_i2c1_resource),
> +       .resource               = s5pv210_i2c1_resource,
> +};
> +
> +SAMSUNG_DEVICE_INIT(SAMSUNG_S5PV210, SAMSUNG_DEVICE_I2C, s5pv210_i2c1_device);
> +
> +static struct resource s5pv210_i2c2_resource[] = {
> +       [0] = {
> +               .start = S5PV210_PA_IIC2,
> +               .end   = S5PV210_PA_IIC2 + SZ_4K - 1,
> +               .flags = IORESOURCE_MEM,
> +       },
> +       [1] = {
> +               .start = S5PV210_IRQ_I2C2,
> +               .end   = S5PV210_IRQ_I2C2,
> +               .flags = IORESOURCE_IRQ,
> +       },
> +};
> +
> +static void s5pv210_i2c2_cfg_gpio(struct platform_device *dev)
> +{
> +       s3c_gpio_cfgpin(S5PV210_GPD1(4), S3C_GPIO_SFN(2));
> +       s3c_gpio_setpull(S5PV210_GPD1(4), S3C_GPIO_PULL_UP);
> +       s3c_gpio_cfgpin(S5PV210_GPD1(5), S3C_GPIO_SFN(2));
> +       s3c_gpio_setpull(S5PV210_GPD1(5), S3C_GPIO_PULL_UP);
> +}
> +
> +static struct s3c2410_platform_i2c s5pv210_i2c2_data = {
> +       .bus_num                = 2,
> +       .slave_addr             = 0x10,
> +       .frequency              = 400*1000,
> +       .sda_delay              = 100,
> +       .cfg_gpio               = s5pv210_i2c2_cfg_gpio,
> +};
> +
> +static struct platform_device s5pv210_i2c2_device = {
> +       .name                   = "s3c2440-i2c",
> +       .id                     = 2,
> +       .dev                    = {
> +               .platform_data  = &s5pv210_i2c2_data,
> +       },
> +       .num_resources          = ARRAY_SIZE(s5pv210_i2c2_resource),
> +       .resource               = s5pv210_i2c2_resource,
> +};
> +
> +SAMSUNG_DEVICE_INIT(SAMSUNG_S5PV210, SAMSUNG_DEVICE_I2C, s5pv210_i2c2_device);
> diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
> index 9689537..fe48c7f 100644
> --- a/arch/arm/mach-s5pv210/include/mach/irqs.h
> +++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
> @@ -51,11 +51,13 @@
>  #define IRQ_UART2              S5P_IRQ_VIC1(12)
>  #define IRQ_UART3              S5P_IRQ_VIC1(13)
>  #define IRQ_IIC                        S5P_IRQ_VIC1(14)
> +#define S5PV210_IRQ_I2C0       S5P_IRQ_VIC1(14)
>  #define IRQ_SPI0               S5P_IRQ_VIC1(15)
>  #define IRQ_SPI1               S5P_IRQ_VIC1(16)
>  #define IRQ_SPI2               S5P_IRQ_VIC1(17)
>  #define IRQ_IRDA               S5P_IRQ_VIC1(18)
> -#define IRQ_CAN0               S5P_IRQ_VIC1(19)
> +#define IRQ_IIC2               S5P_IRQ_VIC1(19)
> +#define S5PV210_IRQ_I2C2       S5P_IRQ_VIC1(19)
>  #define IRQ_CAN1               S5P_IRQ_VIC1(20)
>  #define IRQ_HSIRX              S5P_IRQ_VIC1(21)
>  #define IRQ_HSITX              S5P_IRQ_VIC1(22)
> @@ -85,6 +87,7 @@
>  #define IRQ_MIXER              S5P_IRQ_VIC2(11)
>  #define IRQ_HDMI               S5P_IRQ_VIC2(12)
>  #define IRQ_IIC1               S5P_IRQ_VIC2(13)
> +#define S5PV210_IRQ_I2C1       S5P_IRQ_VIC2(13)
>  #define IRQ_MFC                        S5P_IRQ_VIC2(14)
>  #define IRQ_TVENC              S5P_IRQ_VIC2(15)
>  #define IRQ_I2S0               S5P_IRQ_VIC2(16)
> diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
> index b1d82cc..f2a91f3 100644
> --- a/arch/arm/plat-samsung/Makefile
> +++ b/arch/arm/plat-samsung/Makefile
> @@ -30,6 +30,7 @@ obj-$(CONFIG_S3C_ADC) += adc.o
>
>  # devices
>
> +obj-y                          += devices.o
>  obj-$(CONFIG_S3C_DEV_HSMMC)    += dev-hsmmc.o
>  obj-$(CONFIG_S3C_DEV_HSMMC1)   += dev-hsmmc1.o
>  obj-$(CONFIG_S3C_DEV_HSMMC2)   += dev-hsmmc2.o
> diff --git a/arch/arm/plat-samsung/devices.c b/arch/arm/plat-samsung/devices.c
> new file mode 100644
> index 0000000..0db6555
> --- /dev/null
> +++ b/arch/arm/plat-samsung/devices.c
> @@ -0,0 +1,102 @@
> +/*
> + * linux/arch/arm/plat-samsung/devices.c
> + *
> + *  Copyright 2010 Samsung Electronics
> + *
> + * Sasmung SoCs series device helper functions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/list.h>
> +
> +#include <plat/samsung_device.h>
> +
> +static struct list_head samsung_devices_list[SAMSUNG_NUM_SOC];
> +
> +static struct samsung_device *samsung_find_device(struct samsung_device *sdev)
> +{
> +       struct samsung_device *sd;
> +
> +       list_for_each_entry(sd, &samsung_devices_list[sdev->soc], list) {
> +               if (sd->type == sdev->type &&
> +                   sd->pdev->id == sdev->id) {
> +                       return sd;
> +               }
> +       }
> +
> +       return NULL;
> +}
> +
> +static void samsung_device_unregister(struct samsung_device *sdevs, int num)
> +{
> +       struct samsung_device *sd;
> +       int i;
> +
> +       for (i = 0; i < num; i++) {
> +               sd = samsung_find_device(&sdevs[i]);
> +               if (!sd)
> +                       continue;
> +
> +               platform_device_unregister(sd->pdev);
> +       }
> +}
> +
> +int samsung_platform_add_devices(struct samsung_device *sdevs, int num)
> +{
> +       struct samsung_device *sd;
> +       int i, ret = 0;
> +
> +       for (i = 0; i < num; i++) {
> +               sd = samsung_find_device(&sdevs[i]);
> +               if (!sd)
> +                       continue;
> +
> +               ret = platform_device_register(sd->pdev);
> +               if (ret) {
> +                       samsung_device_unregister(sdevs, num);
> +                       break;
> +               }
> +       }
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL(samsung_platform_add_devices);
> +
> +int samsung_device_register(enum samsung_soc soc,
> +               enum samsung_device_type type, struct platform_device *pdev)
> +{
> +       struct samsung_device *sd;
> +
> +       sd = kzalloc(sizeof(struct samsung_device), GFP_KERNEL);
> +       if (!sd)
> +               return -ENOMEM;
> +
> +       printk(KERN_INFO "samsung %d device type %d, name %s, id %d\n",
> +                               soc, type, pdev->name, pdev->id);
> +
> +       INIT_LIST_HEAD(&sd->list);
> +       sd->soc = soc;
> +       sd->type = type;
> +       sd->pdev = pdev;
> +       list_add(&sd->list, &samsung_devices_list[soc]);
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL(samsung_device_register);
> +
> +static int __init samsung_device_init(void)
> +{
> +       int i;
> +
> +       for (i = 0; i < SAMSUNG_NUM_SOC; i++)
> +               INIT_LIST_HEAD(&samsung_devices_list[i]);
> +       return 0;
> +}
> +
> +pure_initcall(samsung_device_init);
> diff --git a/arch/arm/plat-samsung/include/plat/samsung_device.h b/arch/arm/plat-samsung/include/plat/samsung_device.h
> new file mode 100644
> index 0000000..8bb134a
> --- /dev/null
> +++ b/arch/arm/plat-samsung/include/plat/samsung_device.h
> @@ -0,0 +1,53 @@
> +/*
> + * arch/arm/mach-s5pv210/devices.c
> + *
> + *  Copyright 2010 Samsung Electronics
> + *  Kyungmin Park <kyungmin.park at samsung.com>
> + *
> + * Sasmung SoCs series devices definitions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __SAMSUNG_DEVICE_H
> +#define __SAMSUNG_DEVICE_H
> +
> +#include <linux/init.h>
> +
> +enum samsung_soc {
> +       SAMSUNG_S5PV210,
> +       SAMSUNG_NUM_SOC,
> +};
> +
> +enum samsung_device_type {
> +       SAMSUNG_DEVICE_I2C,
> +};
> +
> +struct samsung_device {
> +       struct list_head                list;
> +       enum samsung_soc                soc;
> +       enum samsung_device_type        type;
> +       int                             id;
> +       struct platform_device          *pdev;
> +};
> +
> +extern int samsung_platform_add_devices(struct samsung_device *sdevs, int num);
> +extern int samsung_device_register(enum samsung_soc soc,
> +               enum samsung_device_type type, struct platform_device *pdev);
> +
> +#define SAMSUNG_DEVICE_ID(dev_soc, dev_type, dev_id)                   \
> +{      .soc = dev_soc, .type = SAMSUNG_DEVICE_##dev_type, .id = dev_id, }
> +
> +#define S5PV210_DEVICE_ID(dev_type, dev_id)                            \
> +       SAMSUNG_DEVICE_ID(SAMSUNG_S5PV210, dev_type, dev_id)
> +
> +#define SAMSUNG_DEVICE_INIT(soc, type, pdev)                           \
> +static int samsung_device_init_##pdev(void)                            \
> +{                                                                      \
> +       return samsung_device_register(soc, type, &pdev);               \
> +}                                                                      \
> +core_initcall(samsung_device_init_##pdev)
> +
> +#endif
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>



More information about the linux-arm-kernel mailing list