[RFC, PATCH 3/3] gpiodev - ASIC3 SoC implementation (informal)

From: Paul Sokolovsky
Date: Tue Apr 10 2007 - 17:44:50 EST


Hello linux-arm-kernel,

GPIODEV API: Support for ASIC3 SoC, found in several PDAs from HP and
HTC.
Note: ASIC3 driver is not yet in mainline (GPIODEV is one thing on
critical path to have it submitted), and itself is pretty packaged
System-on-Chip with many controllers, and thus big drivers. Patch
below shows snippets relevant to its GPIO controller, as a sample what
changes should be made to a generic driver for a GPIO-providing
device to make it GPIODEV-compliant. Full driver can be found at
http://handhelds.org/cgi-bin/cvsweb.cgi/~checkout~/linux/kernel26/drivers/soc/asic3_base.c?content-type=text/plain&f=h

Signed-off-by: Paul Sokolovsky <pmiscml@xxxxxxxxx>


Index: include/linux/soc/asic3_base.h
===================================================================
RCS file: include/linux/soc/asic3_base.h
diff -N include/linux/soc/asic3_base.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ include/linux/soc/asic3_base.h 10 Apr 2007 15:35:33 -0000 1.12
@@ -0,0 +1,98 @@
+#include <linux/gpiodev.h>
+
+/* Private defines - for internal use only */
+#define HDR_IPAQ_ASIC3_ACTION(ACTION,action,fn,FN) \
+u32 asic3_get_gpio_ ## action ## _ ## fn (struct device *dev); \
+void asic3_set_gpio_ ## action ## _ ## fn (struct device *dev, u32 bits, u32 val);
+
+#define HDR_IPAQ_ASIC3_FN(fn,FN) \
+ HDR_IPAQ_ASIC3_ACTION ( MASK,mask,fn,FN) \
+ HDR_IPAQ_ASIC3_ACTION ( DIR, dir, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( OUT, out, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( LEVELTRI, trigtype, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( RISING, rising, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( LEVEL, triglevel, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( SLEEP_MASK, sleepmask, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( SLEEP_OUT, sleepout, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( BATT_FAULT_OUT, battfaultout, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( INT_STATUS, intstatus, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( ALT_FUNCTION, alt_fn, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( SLEEP_CONF, sleepconf, fn, FN) \
+ HDR_IPAQ_ASIC3_ACTION ( STATUS, status, fn, FN)
+
+#define ASIC3_GPIOA_IRQ_BASE 0
+#define ASIC3_GPIOB_IRQ_BASE 16
+#define ASIC3_GPIOC_IRQ_BASE 32
+#define ASIC3_GPIOD_IRQ_BASE 48
+#define ASIC3_LED0_IRQ 64
+#define ASIC3_LED1_IRQ 65
+#define ASIC3_LED2_IRQ 66
+#define ASIC3_SPI_IRQ 67
+#define ASIC3_SMBUS_IRQ 68
+#define ASIC3_OWM_IRQ 69
+
+#define ASIC3_NR_GPIO_IRQS 64 /* 16 bits each GPIO A...D banks */
+#define ASIC3_NR_IRQS (ASIC3_OWM_IRQ + 1)
+
+/* Public API */
+
+extern int asic3_irq_base (struct device *dev);
+
+void asic3_write_register (struct device *dev, unsigned int reg, unsigned long value);
+unsigned long asic3_read_register (struct device *dev, unsigned int reg);
+
+/* old clock api */
+extern void asic3_set_clock_sel (struct device *dev, unsigned long bits, unsigned long val);
+extern u32 asic3_get_clock_cdex (struct device *dev);
+extern void asic3_set_clock_cdex (struct device *dev, unsigned long bits, unsigned long val);
+
+extern void asic3_set_extcf_select (struct device *dev, unsigned long bits, unsigned long val);
+extern void asic3_set_extcf_reset (struct device *dev, unsigned long bits, unsigned long val);
+extern void asic3_set_sdhwctrl (struct device *dev, unsigned long bits, unsigned long val);
+
+void asic3_set_led( struct device *dev, int led_num, int duty_time, int cycle_time);
+
+extern int asic3_register_mmc (struct device *dev);
+extern int asic3_unregister_mmc (struct device *dev);
+
+/* Accessors for GPIO banks */
+HDR_IPAQ_ASIC3_FN(a, A)
+HDR_IPAQ_ASIC3_FN(b, B)
+HDR_IPAQ_ASIC3_FN(c, C)
+HDR_IPAQ_ASIC3_FN(d, D)
+
+#define _IPAQ_ASIC3_GPIO_BANK_A 0
+#define _IPAQ_ASIC3_GPIO_BANK_B 1
+#define _IPAQ_ASIC3_GPIO_BANK_C 2
+#define _IPAQ_ASIC3_GPIO_BANK_D 3
+
+#define ASIC3_GPIO_bit(gpio) (1 << (gpio & 0xf))
+
+extern int asic3_get_gpio_bit(struct device *dev, int gpio);
+extern void asic3_set_gpio_bit(struct device *dev, int gpio, int val);
+
+
+struct tmio_mmc_hwconfig;
+
+struct asic3_platform_data
+{
+ // Must be first member
+ struct gpiodev_ops gpiodev_ops;
+
+ struct {
+ u32 dir;
+ u32 init;
+ u32 sleep_mask;
+ u32 sleep_out;
+ u32 batt_fault_out;
+ u32 sleep_conf;
+ u32 alt_function;
+ } gpio_a, gpio_b, gpio_c, gpio_d;
+
+ unsigned long bus_shift;
+
+ struct platform_device **child_platform_devs;
+ int num_child_platform_devs;
+
+ struct tmio_mmc_hwconfig *tmio_mmc_hwconfig;
+};
Index: drivers/soc/asic3_base.c
===================================================================
RCS file: /cvs/linux/kernel26/drivers/soc/asic3_base.c,v
retrieving revision 1.40
retrieving revision 1.42
diff -u -p -r1.40 -r1.42
--- drivers/soc/asic3_base.c 14 Feb 2007 13:54:49 -0000 1.40
+++ drivers/soc/asic3_base.c 10 Apr 2007 15:35:33 -0000 1.42
@@ -145,6 +145,7 @@ ASIC3_GPIO_FUNCTIONS(d, D)
int asic3_get_gpio_bit(struct device *dev, int gpio)
{
u32 mask = ASIC3_GPIO_bit(gpio);
+ printk("%s(%d)\n", __FUNCTION__, gpio);
switch (gpio >> 4) {
case _IPAQ_ASIC3_GPIO_BANK_A:
return asic3_get_gpio_status_a(dev) & mask;
@@ -166,6 +167,7 @@ void asic3_set_gpio_bit(struct device *d
u32 mask = ASIC3_GPIO_bit(gpio);
u32 bitval = 0;
if (val) bitval = mask;
+ printk("%s(%d, %d)\n", __FUNCTION__, gpio, val);

switch (gpio >> 4) {
case _IPAQ_ASIC3_GPIO_BANK_A:
@@ -196,6 +198,14 @@ asic3_irq_base (struct device *dev)

EXPORT_SYMBOL(asic3_irq_base);

+int asic3_gpio_to_irq(struct device *dev, int gpio)
+{
+ struct asic3_data *asic = dev->driver_data;
+ printk("%s(%d)\n", __FUNCTION__, gpio);
+
+ return asic->irq_base + gpio;
+}
+
void
asic3_set_led (struct device *dev, int led_num, int duty_time, int cycle_time)
{
@@ -1027,6 +1037,10 @@ asic3_probe(struct platform_device *pdev
ds1wm_pd.bus_shift = asic->bus_shift;
#endif

+ pdata->gpiodev_ops.get = asic3_get_gpio_bit;
+ pdata->gpiodev_ops.set = asic3_set_gpio_bit;
+ pdata->gpiodev_ops.to_irq = asic3_gpio_to_irq;
+
soc_add_devices(pdev, asic3_blocks, ARRAY_SIZE(asic3_blocks),
&pdev->resource[0], asic->bus_shift - ASIC3_DEFAULT_ADDR_SHIFT, asic->irq_base);



--
Best regards,
Paul mailto:pmiscml@xxxxxxxxx

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/