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 <[EMAIL PROTECTED]>


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:[EMAIL PROTECTED]

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

Reply via email to