Linux-2.6.12-rc2
[linux-2.6.git] / include / asm-ppc / ocp.h
1 /*
2  * ocp.h
3  *
4  *      (c) Benjamin Herrenschmidt (benh@kernel.crashing.org)
5  *          Mipsys - France
6  *
7  *          Derived from work (c) Armin Kuster akuster@pacbell.net
8  *
9  *          Additional support and port to 2.6 LDM/sysfs by
10  *          Matt Porter <mporter@kernel.crashing.org>
11  *          Copyright 2003-2004 MontaVista Software, Inc.
12  *
13  * This program is free software; you can redistribute  it and/or modify it
14  * under  the terms of  the GNU General  Public License as published by the
15  * Free Software Foundation;  either version 2 of the  License, or (at your
16  * option) any later version.
17  *
18  *  TODO: - Add get/put interface & fixup locking to provide same API for
19  *          2.4 and 2.5
20  *        - Rework PM callbacks
21  */
22
23 #ifdef __KERNEL__
24 #ifndef __OCP_H__
25 #define __OCP_H__
26
27 #include <linux/init.h>
28 #include <linux/list.h>
29 #include <linux/config.h>
30 #include <linux/devfs_fs_kernel.h>
31 #include <linux/device.h>
32
33 #include <asm/mmu.h>
34 #include <asm/ocp_ids.h>
35 #include <asm/rwsem.h>
36 #include <asm/semaphore.h>
37
38 #ifdef CONFIG_PPC_OCP
39
40 #define OCP_MAX_IRQS    7
41 #define MAX_EMACS       4
42 #define OCP_IRQ_NA      -1      /* used when ocp device does not have an irq */
43 #define OCP_IRQ_MUL     -2      /* used for ocp devices with multiply irqs */
44 #define OCP_NULL_TYPE   -1      /* used to mark end of list */
45 #define OCP_CPM_NA      0       /* No Clock or Power Management avaliable */
46 #define OCP_PADDR_NA    0       /* No MMIO registers */
47
48 #define OCP_ANY_ID      (~0)
49 #define OCP_ANY_INDEX   -1
50
51 extern struct list_head         ocp_devices;
52 extern struct rw_semaphore      ocp_devices_sem;
53
54 struct ocp_device_id {
55         unsigned int    vendor, function;       /* Vendor and function ID or OCP_ANY_ID */
56         unsigned long   driver_data;            /* Data private to the driver */
57 };
58
59
60 /*
61  * Static definition of an OCP device.
62  *
63  * @vendor:    Vendor code. It is _STRONGLY_ discouraged to use
64  *             the vendor code as a way to match a unique device,
65  *             though I kept that possibility open, you should
66  *             really define different function codes for different
67  *             device types
68  * @function:  This is the function code for this device.
69  * @index:     This index is used for mapping the Nth function of a
70  *             given core. This is typically used for cross-driver
71  *             matching, like looking for a given MAL or ZMII from
72  *             an EMAC or for getting to the proper set of DCRs.
73  *             Indices are no longer magically calculated based on
74  *             structure ordering, they have to be actually coded
75  *             into the ocp_def to avoid any possible confusion
76  *             I _STRONGLY_ (again ? wow !) encourage anybody relying
77  *             on index mapping to encode the "target" index in an
78  *             associated structure pointed to by "additions", see
79  *             how it's done for the EMAC driver.
80  * @paddr:     Device physical address (may not mean anything...)
81  * @irq:       Interrupt line for this device (TODO: think about making
82  *             an array with this)
83  * @pm:        Currently, contains the bitmask in CPMFR DCR for the device
84  * @additions: Optionally points to a function specific structure
85  *             providing additional informations for a given device
86  *             instance. It's currently used by the EMAC driver for MAL
87  *             channel & ZMII port mapping among others.
88  * @show:      Optionally points to a function specific structure
89  *             providing a sysfs show routine for additions fields.
90  */
91 struct ocp_def {
92         unsigned int    vendor;
93         unsigned int    function;
94         int             index;
95         phys_addr_t     paddr;
96         int             irq;
97         unsigned long   pm;
98         void            *additions;
99         void            (*show)(struct device *);
100 };
101
102
103 /* Struct for a given device instance */
104 struct ocp_device {
105         struct list_head        link;
106         char                    name[80];       /* device name */
107         struct ocp_def          *def;           /* device definition */
108         void                    *drvdata;       /* driver data for this device */
109         struct ocp_driver       *driver;
110         u32                     current_state;  /* Current operating state. In ACPI-speak,
111                                                    this is D0-D3, D0 being fully functional,
112                                                    and D3 being off. */
113         struct                  device dev;
114 };
115
116 struct ocp_driver {
117         struct list_head node;
118         char *name;
119         const struct ocp_device_id *id_table;   /* NULL if wants all devices */
120         int  (*probe)  (struct ocp_device *dev);        /* New device inserted */
121         void (*remove) (struct ocp_device *dev);        /* Device removed (NULL if not a hot-plug capable driver) */
122         int  (*suspend) (struct ocp_device *dev, u32 state);    /* Device suspended */
123         int  (*resume) (struct ocp_device *dev);                        /* Device woken up */
124         struct device_driver driver;
125 };
126
127 #define to_ocp_dev(n) container_of(n, struct ocp_device, dev)
128 #define to_ocp_drv(n) container_of(n, struct ocp_driver, driver)
129
130 /* Similar to the helpers above, these manipulate per-ocp_dev
131  * driver-specific data.  Currently stored as ocp_dev::ocpdev,
132  * a void pointer, but it is not present on older kernels.
133  */
134 static inline void *
135 ocp_get_drvdata(struct ocp_device *pdev)
136 {
137         return pdev->drvdata;
138 }
139
140 static inline void
141 ocp_set_drvdata(struct ocp_device *pdev, void *data)
142 {
143         pdev->drvdata = data;
144 }
145
146 #if defined (CONFIG_PM)
147 /*
148  * This is right for the IBM 405 and 440 but will need to be
149  * generalized if the OCP stuff gets used on other processors.
150  */
151 static inline void
152 ocp_force_power_off(struct ocp_device *odev)
153 {
154         mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | odev->def->pm);
155 }
156
157 static inline void
158 ocp_force_power_on(struct ocp_device *odev)
159 {
160         mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~odev->def->pm);
161 }
162 #else
163 #define ocp_force_power_off(x)  (void)(x)
164 #define ocp_force_power_on(x)   (void)(x)
165 #endif
166
167 /* Register/Unregister an OCP driver */
168 extern int ocp_register_driver(struct ocp_driver *drv);
169 extern void ocp_unregister_driver(struct ocp_driver *drv);
170
171 /* Build list of devices */
172 extern int ocp_early_init(void) __init;
173
174 /* Find a device by index */
175 extern struct ocp_device *ocp_find_device(unsigned int vendor, unsigned int function, int index);
176
177 /* Get a def by index */
178 extern struct ocp_def *ocp_get_one_device(unsigned int vendor, unsigned int function, int index);
179
180 /* Add a device by index */
181 extern int ocp_add_one_device(struct ocp_def *def);
182
183 /* Remove a device by index */
184 extern int ocp_remove_one_device(unsigned int vendor, unsigned int function, int index);
185
186 /* Iterate over devices and execute a routine */
187 extern void ocp_for_each_device(void(*callback)(struct ocp_device *, void *arg), void *arg);
188
189 /* Sysfs support */
190 #define OCP_SYSFS_ADDTL(type, format, name, field)                      \
191 static ssize_t                                                          \
192 show_##name##_##field(struct device *dev, char *buf)                    \
193 {                                                                       \
194         struct ocp_device *odev = to_ocp_dev(dev);                      \
195         type *add = odev->def->additions;                               \
196                                                                         \
197         return sprintf(buf, format, add->field);                        \
198 }                                                                       \
199 static DEVICE_ATTR(name##_##field, S_IRUGO, show_##name##_##field, NULL);
200
201 #ifdef CONFIG_IBM_OCP
202 #include <asm/ibm_ocp.h>
203 #endif
204
205 #ifdef CONFIG_FSL_OCP
206 #include <asm/fsl_ocp.h>
207 #endif
208
209 #endif                          /* CONFIG_PPC_OCP */
210 #endif                          /* __OCP_H__ */
211 #endif                          /* __KERNEL__ */