Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.17-rc5 207 lines 7.0 kB view raw
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 51extern struct list_head ocp_devices; 52extern struct rw_semaphore ocp_devices_sem; 53 54struct 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 */ 91struct 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 */ 104struct 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 116struct 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, pm_message_t 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 */ 134static inline void * 135ocp_get_drvdata(struct ocp_device *pdev) 136{ 137 return pdev->drvdata; 138} 139 140static inline void 141ocp_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 */ 151static inline void 152ocp_force_power_off(struct ocp_device *odev) 153{ 154 mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | odev->def->pm); 155} 156 157static inline void 158ocp_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 */ 168extern int ocp_register_driver(struct ocp_driver *drv); 169extern void ocp_unregister_driver(struct ocp_driver *drv); 170 171/* Build list of devices */ 172extern int ocp_early_init(void) __init; 173 174/* Find a device by index */ 175extern struct ocp_device *ocp_find_device(unsigned int vendor, unsigned int function, int index); 176 177/* Get a def by index */ 178extern struct ocp_def *ocp_get_one_device(unsigned int vendor, unsigned int function, int index); 179 180/* Add a device by index */ 181extern int ocp_add_one_device(struct ocp_def *def); 182 183/* Remove a device by index */ 184extern int ocp_remove_one_device(unsigned int vendor, unsigned int function, int index); 185 186/* Iterate over devices and execute a routine */ 187extern 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) \ 191static ssize_t \ 192show_##name##_##field(struct device *dev, struct device_attribute *attr, 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} \ 199static 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#endif /* CONFIG_PPC_OCP */ 206#endif /* __OCP_H__ */ 207#endif /* __KERNEL__ */