From: Paul Butler <paul.but...@windriver.com> This patch adds the register definitions, support for PW messages, destination IDs, direct IO and driver support.
Signed-off-by: Paul Butler <paul.but...@windriver.com> --- include/asm-generic/vmlinux.lds.h | 10 ++ include/linux/rio.h | 231 ++++++++++++++++++++++++++++++------- include/linux/rio_dio.h | 67 +++++++++++ include/linux/rio_drv.h | 202 +++++++++++++++++++++++++------- include/linux/rio_ids.h | 7 ++ include/linux/rio_regs.h | 26 +++++ include/linux/riopw.h | 30 +++++ 7 files changed, 490 insertions(+), 83 deletions(-) create mode 100644 include/linux/rio_dio.h create mode 100644 include/linux/riopw.h diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 5d2ca6f..290711d 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -274,6 +274,16 @@ } \ \ /* RapidIO route ops */ \ + .rio_dev_fixup : AT(ADDR(.rio_dev_fixup) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start_rio_dev_fixup_early) = .; \ + *(.rio_dev_fixup_early) \ + VMLINUX_SYMBOL(__end_rio_dev_fixup_early) = .; \ + VMLINUX_SYMBOL(__start_rio_dev_fixup_enable) = .; \ + *(.rio_dev_fixup_enable) \ + VMLINUX_SYMBOL(__end_rio_dev_fixup_enable) = .; \ + } \ + \ + /* RapidIO route ops */ \ .rio_ops : AT(ADDR(.rio_ops) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start_rio_switch_ops) = .; \ *(.rio_switch_ops) \ diff --git a/include/linux/rio.h b/include/linux/rio.h index 4d50611..ef300e2 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -20,6 +20,8 @@ #include <linux/errno.h> #include <linux/device.h> #include <linux/rio_regs.h> +#include <linux/radix-tree.h> +#include <asm/rio.h> #define RIO_NO_HOPCOUNT -1 #define RIO_INVALID_DESTID 0xffff @@ -37,10 +39,14 @@ entry is invalid (no route exists for the device ID) */ +#define RIO_INVALID_ROUTE_WEIGHT 0xff /* Indicates that a route weight + entry is invalid (no route + exists for the device ID) */ + #define RIO_MAX_ROUTE_ENTRIES(size) (size ? (1 << 16) : (1 << 8)) #define RIO_ANY_DESTID(size) (size ? 0xffff : 0xff) -#define RIO_MAX_MBOX 4 +#define RIO_MAX_MBOX 8 #define RIO_MAX_MSG_SIZE 0x1000 /* @@ -77,6 +83,9 @@ #define RIO_CTAG_RESRVD 0xfffe0000 /* Reserved */ #define RIO_CTAG_UDEVID 0x0001ffff /* Unique device identifier */ +#define RIO_DEVICE_INSERTION 1 +#define RIO_DEVICE_EXTRACTION 2 + extern struct bus_type rio_bus_type; extern struct device rio_bus; extern struct list_head rio_devices; /* list of all devices */ @@ -85,6 +94,15 @@ struct rio_mport; struct rio_dev; union rio_pw_msg; +struct rio_switch_port { + struct rio_dev *rdev; +#ifdef CONFIG_RAPIDIO_DYNAMIC_ROUTES + u8 *route_weights_table; +#endif +}; + +#define NEW_STYLE 1 + /** * struct rio_switch - RIO switch info * @node: Node in global list of switches @@ -104,7 +122,12 @@ union rio_pw_msg; struct rio_switch { struct list_head node; u16 switchid; +#ifdef OLD_STYLE u8 *route_table; +#else + u32 port_init; + int update_lut; +#endif u32 port_ok; int (*add_entry) (struct rio_mport *mport, u16 destid, u8 hopcount, u16 table, u16 route_destid, u8 route_port); @@ -119,7 +142,9 @@ struct rio_switch { int (*em_init) (struct rio_dev *dev); int (*em_handle) (struct rio_dev *dev, u8 swport); int (*sw_sysfs) (struct rio_dev *dev, int create); - struct rio_dev *nextdev[0]; +#ifdef OLD_STYLE + struct rio_switch_port port[0]; +#endif }; /** @@ -151,10 +176,19 @@ struct rio_switch { * @prev: Previous RIO device connected to the current one * @rswitch: struct rio_switch (if valid for this device) */ +#ifdef NEW_STYLE +struct rio_dyn { + int prev_port; + u16 prev_destid; + u32 swpinfo; +}; +#endif + struct rio_dev { struct list_head global_list; /* node in list of all RIO devices */ struct list_head net_list; /* node in per net list */ - struct rio_net *net; /* RIO net this device resides in */ + struct list_head route_list; /* node in per net list */ + struct rio_mport *hport; /* RIO net this device resides in */ u16 did; u16 vid; u32 device_rev; @@ -176,7 +210,15 @@ struct rio_dev { int (*pwcback) (struct rio_dev *rdev, union rio_pw_msg *msg, int step); u16 destid; u8 hopcount; +#ifdef NEW_STYLE + int use_hw_lock; + int local_domain; /* Device enumerated/Device discovered */ + int prev_port; + u16 prev_destid; + u8 return_port; +#else struct rio_dev *prev; +#endif struct rio_switch rswitch[0]; /* RIO switch info */ }; @@ -190,9 +232,15 @@ struct rio_dev { * @res: Mailbox resource * @mcback: Message event callback */ -struct rio_msg { +struct rio_outb_msg { struct resource *res; - void (*mcback) (struct rio_mport * mport, void *dev_id, int mbox, int slot); + void (*mcback) (struct rio_mport *mport, + void *dev_id, int mbox, int rc, void *cookie); +}; +struct rio_inb_msg { + struct resource *res; + void (*mcback) (struct rio_mport *mport, + void *dev_id, int mbox, int letter); }; /** @@ -205,7 +253,8 @@ struct rio_msg { struct rio_dbell { struct list_head node; struct resource *res; - void (*dinb) (struct rio_mport *mport, void *dev_id, u16 src, u16 dst, u16 info); + void (*dinb) (struct rio_mport *mport, void *dev_id, + u16 src, u16 dst, u16 info); void *dev_id; }; @@ -214,6 +263,46 @@ enum rio_phy_type { RIO_PHY_SERIAL, }; +struct rio_map_addr { + void __iomem *va; + resource_size_t phys; +}; + +/** + * Struct for RIO memory definition. + * @req_outb: The function for requesting outbound memory window. + * @map_outb: The function for mapping outbound memory window. + * @release_outb: The function for releasing outbound memory window. + */ +struct rio_mem_ops { + int (*req_outb) (struct rio_mport *, resource_size_t, + const char *, u32, u32 *); + int (*map_outb) (struct rio_mport *, u32, + u16, u32, u32, struct rio_map_addr *); + void (*release_outb) (struct rio_mport *, u32); +}; +/** + * struct rio_net - RIO network info + * @node: Node in global list of RIO networks + * @devices: List of devices in this network + * @mports: List of master ports accessing this network + * @hport: Default port for accessing this network + * @id: RIO network ID + */ +struct rio_net { +#ifdef NEW_STYLE + struct radix_tree_root dev_tree; + atomic_t rio_dev_num; + struct radix_tree_root dst_tree; + atomic_t rio_dst_num; + atomic_t rio_max_dest; + spinlock_t tree_lock; +#else + struct list_head devices; /* list of devices in this net */ +#endif + unsigned char id; /* RIO network ID */ +}; + /** * struct rio_mport - RIO master port info * @dbells: List of doorbell events @@ -236,13 +325,19 @@ enum rio_phy_type { struct rio_mport { struct list_head dbells; /* list of doorbell events */ struct list_head node; /* node in global list of ports */ - struct list_head nnode; /* node in net list of ports */ + struct rio_net net; + +#if defined(CONFIG_RAPIDIO_STATIC_DESTID) || defined(CONFIG_RAPIDIO_HOTPLUG) + struct device dev; +#endif struct resource iores; struct resource riores[RIO_MAX_MPORT_RESOURCES]; - struct rio_msg inb_msg[RIO_MAX_MBOX]; - struct rio_msg outb_msg[RIO_MAX_MBOX]; + struct rio_inb_msg inb_msg[RIO_MAX_MBOX]; + struct rio_outb_msg outb_msg[RIO_MAX_MBOX]; int host_deviceid; /* Host device ID */ + int enum_host; struct rio_ops *ops; /* low-level architecture-dependent routines */ + struct rio_mem_ops *mops; /* Memory functions */ unsigned char id; /* port ID, unique among all ports */ unsigned char index; /* port index, unique among all port interfaces of the same type */ @@ -256,28 +351,33 @@ struct rio_mport { void *priv; /* Master port private data */ }; -/** - * struct rio_net - RIO network info - * @node: Node in global list of RIO networks - * @devices: List of devices in this network - * @mports: List of master ports accessing this network - * @hport: Default port for accessing this network - * @id: RIO network ID - */ -struct rio_net { - struct list_head node; /* node in list of networks */ - struct list_head devices; /* list of devices in this net */ - struct list_head mports; /* list of ports accessing net */ - struct rio_mport *hport; /* primary port for accessing net */ - unsigned char id; /* RIO network ID */ -}; /* Definitions used by switch sysfs initialization callback */ #define RIO_SW_SYSFS_CREATE 1 /* Create switch attributes */ #define RIO_SW_SYSFS_REMOVE 0 /* Remove switch attributes */ /* Low-level architecture-dependent routines */ - +#ifdef CONFIG_RAPIDIO_HOTPLUG + +#define RIO_HOT_SWAP_EXTRACT 0x1 +#define RIO_HOT_SWAP_INSERT 0x2 +#define RIO_HOT_SWAP_MPORT 0x4 +#define RIO_HOT_SWAP_LINK_PARTNER 0x8 + +#define RIO_EXTRACT_LP(f) (((f) & \ + (RIO_HOT_SWAP_EXTRACT | RIO_HOT_SWAP_LINK_PARTNER)) == \ + (RIO_HOT_SWAP_EXTRACT | RIO_HOT_SWAP_LINK_PARTNER)) +#define RIO_EXTRACT_MP(f) (((f) & \ + (RIO_HOT_SWAP_EXTRACT | RIO_HOT_SWAP_MPORT)) == \ + (RIO_HOT_SWAP_EXTRACT | RIO_HOT_SWAP_MPORT)) +#define RIO_INSERT_LP(f) (((f) & \ + (RIO_HOT_SWAP_INSERT | RIO_HOT_SWAP_LINK_PARTNER)) == \ + (RIO_HOT_SWAP_INSERT | RIO_HOT_SWAP_LINK_PARTNER)) +#define RIO_INSERT_MP(f) (((f) & \ + (RIO_HOT_SWAP_INSERT | RIO_HOT_SWAP_MPORT)) == \ + (RIO_HOT_SWAP_INSERT | RIO_HOT_SWAP_MPORT)) + +#endif /** * struct rio_ops - Low-level RIO configuration space operations * @lcread: Callback to perform local (master port) read of config space. @@ -295,28 +395,47 @@ struct rio_net { * @get_inb_message: Callback to get a message from an inbound mailbox queue. */ struct rio_ops { - int (*lcread) (struct rio_mport *mport, int index, u32 offset, int len, - u32 *data); - int (*lcwrite) (struct rio_mport *mport, int index, u32 offset, int len, - u32 data); + int (*lcread) (struct rio_mport *mport, int index, u32 offset, + int len, u32 *data); + int (*lcwrite) (struct rio_mport *mport, int index, u32 offset, + int len, u32 data); int (*cread) (struct rio_mport *mport, int index, u16 destid, u8 hopcount, u32 offset, int len, u32 *data); int (*cwrite) (struct rio_mport *mport, int index, u16 destid, u8 hopcount, u32 offset, int len, u32 data); - int (*dsend) (struct rio_mport *mport, int index, u16 destid, u16 data); + int (*dsend) (struct rio_mport *mport, int index, + u16 destid, u16 data); int (*pwenable) (struct rio_mport *mport, int enable); int (*open_outb_mbox)(struct rio_mport *mport, void *dev_id, - int mbox, int entries); + int mbox, int entries, int prio); void (*close_outb_mbox)(struct rio_mport *mport, int mbox); int (*open_inb_mbox)(struct rio_mport *mport, void *dev_id, int mbox, int entries); void (*close_inb_mbox)(struct rio_mport *mport, int mbox); int (*add_outb_message)(struct rio_mport *mport, struct rio_dev *rdev, - int mbox, void *buffer, size_t len); + int mbox_dest, int letter, int flags, + void *buffer, size_t len, void *cookie); int (*add_inb_buffer)(struct rio_mport *mport, int mbox, void *buf); - void *(*get_inb_message)(struct rio_mport *mport, int mbox); + void *(*get_inb_message)(struct rio_mport *mport, int mbox, int letter, + int *sz, int *slot, u16 *destid); +#ifdef CONFIG_RAPIDIO_HOTPLUG + int (*hotswap)(struct rio_mport *mport, u8 flags); + int (*port_notify_cb)(struct rio_mport *mport, + int enable, + void (*cb)(struct rio_mport *mport)); + int (*port_op_state)(struct rio_mport *mport); +#endif +}; + +#ifdef CONFIG_RAPIDIO_STATIC_DESTID + +struct rio_static_route { + u16 sw_destid; + u8 sw_port; }; +#endif + #define RIO_RESOURCE_MEM 0x00000100 #define RIO_RESOURCE_DOORBELL 0x00000200 #define RIO_RESOURCE_MAILBOX 0x00000400 @@ -341,19 +460,25 @@ struct rio_ops { * Provides info on a RIO device driver for insertion/removal and * power management purposes. */ +struct rio_dynids { + spinlock_t lock; /* protects list, index */ + struct list_head list; /* for IDs added at runtime */ +}; + struct rio_driver { struct list_head node; char *name; const struct rio_device_id *id_table; - int (*probe) (struct rio_dev * dev, const struct rio_device_id * id); - void (*remove) (struct rio_dev * dev); - int (*suspend) (struct rio_dev * dev, u32 state); - int (*resume) (struct rio_dev * dev); - int (*enable_wake) (struct rio_dev * dev, u32 state, int enable); + int (*probe) (struct rio_dev *dev, const struct rio_device_id *id); + void (*remove) (struct rio_dev *dev); + int (*suspend) (struct rio_dev *dev, u32 state); + int (*resume) (struct rio_dev *dev); + int (*enable_wake) (struct rio_dev *dev, u32 state, int enable); struct device_driver driver; + struct rio_dynids dynids; }; -#define to_rio_driver(drv) container_of(drv,struct rio_driver, driver) +#define to_rio_driver(drv) container_of(drv, struct rio_driver, driver) /** * struct rio_device_id - RIO device identifier @@ -383,6 +508,25 @@ struct rio_switch_ops { u16 vid, did; int (*init_hook) (struct rio_dev *rdev, int do_enum); }; +struct rio_dev_fixup { + u16 vid, did; + void (*fixup_hook) (struct rio_dev *rdev, u16 destid, u8 hopcount); +}; +enum rio_fixup_pass { + rio_fixup_early, + rio_fixup_enable, +}; + + +#define DECLARE_RIO_DEV_FIXUP_SECTION(section, name, vid, did, fixup_hook) \ + static const struct rio_dev_fixup __rio_dev_fixup_##name __used \ + __section(section) = { vid, did, fixup_hook }; +#define DECLARE_RIO_DEV_FIXUP_EARLY(vid, did, fixup_hook) \ + DECLARE_RIO_DEV_FIXUP_SECTION(.rio_dev_fixup_early, \ + vid##did##fixup_hook, vid, did, fixup_hook) +#define DECLARE_RIO_DEV_FIXUP_ENABLE(vid, did, fixup_hook) \ + DECLARE_RIO_DEV_FIXUP_SECTION(.rio_dev_fixup_enable, \ + vid##did##fixup_hook, vid, did, fixup_hook) union rio_pw_msg { struct { @@ -394,6 +538,13 @@ union rio_pw_msg { } em; u32 raw[RIO_PW_MSG_SIZE/sizeof(u32)]; }; +void rio_fixup_dev(enum rio_fixup_pass pass, + struct rio_dev *rdev, + u16 destid, + u8 hopcount); + + + /* Architecture and hardware-specific functions */ extern int rio_register_mport(struct rio_mport *); @@ -401,5 +552,5 @@ extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_inb_mbox(struct rio_mport *, int); extern int rio_open_outb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_outb_mbox(struct rio_mport *, int); - +extern int rio_init_device(struct rio_dev *rdev); #endif /* LINUX_RIO_H */ diff --git a/include/linux/rio_dio.h b/include/linux/rio_dio.h new file mode 100644 index 0000000..4469278 --- /dev/null +++ b/include/linux/rio_dio.h @@ -0,0 +1,67 @@ +#ifndef _RIO_DIO_H_ +#define _RIO_DIO_H_ + + +#define RIO_IO_READ_HOME 0x00 +#define RIO_MAINT_READ 0x01 +#define RIO_MAINT_WRITE 0x10 +#define RIO_NREAD 0x02 +#define RIO_NWRITE 0x20 +#define RIO_NWRITE_R 0x40 +#define RIO_SWRITE 0x80 + +#ifdef __KERNEL__ + +#include <linux/kernel.h> +#include <linux/kref.h> +#include <linux/rio.h> +#include <linux/rio_drv.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> + +struct rio_dio_win { + struct list_head node; + void *dio_channel; + struct rio_dev *rdev; + unsigned outb_win; + resource_size_t win_size; + struct kref kref; +}; + +/* + Setup / release methods +*/ +struct rio_dio_win *rio_dio_req_region(void *dio_channel, + struct rio_dev *rdev, + resource_size_t size, + u32 flags); +void rio_dio_region_put(struct rio_dio_win *io_win); +int rio_dio_method_setup(void **dio_channel); +void rio_dio_method_put(void *dio_channel); + +/* + Access methods +*/ +int rio_dio_read_8(struct rio_dio_win *io_win, u32 offset, + u32 mflags, u8 *value); +int rio_dio_read_16(struct rio_dio_win *io_win, u32 offset, + u32 mflags, u16 *value); +int rio_dio_read_32(struct rio_dio_win *io_win, u32 offset, + u32 mflags, u32 *value); +int rio_dio_read_buff(struct rio_dio_win *io_win, u32 offset, + u8 *dst, u32 mflags, u32 len); +int rio_dio_write_8(struct rio_dio_win *io_win, + u32 offset, u32 mflags, u8 *src); +int rio_dio_write_16(struct rio_dio_win *io_win, + u32 offset, u32 mflags, u16 *src); +int rio_dio_write_32(struct rio_dio_win *io_win, u32 offset, + u32 mflags, u32 *src); +int rio_dio_write_buff(struct rio_dio_win *io_win, u32 offset, + u8 *src, u32 mflags, u32 len); + +int rio_dio_const_win(struct rio_dio_win *io_win, void *buf, u32 len, + enum dma_data_direction dir, struct rio_map_addr *res); + +#endif /* __KERNEL__ */ + +#endif diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h index 7f07470..c320d77 100644 --- a/include/linux/rio_drv.h +++ b/include/linux/rio_drv.h @@ -21,28 +21,28 @@ #include <linux/rio.h> extern int __rio_local_read_config_32(struct rio_mport *port, u32 offset, - u32 * data); + u32 *data); extern int __rio_local_write_config_32(struct rio_mport *port, u32 offset, u32 data); extern int __rio_local_read_config_16(struct rio_mport *port, u32 offset, - u16 * data); + u16 *data); extern int __rio_local_write_config_16(struct rio_mport *port, u32 offset, u16 data); extern int __rio_local_read_config_8(struct rio_mport *port, u32 offset, - u8 * data); + u8 *data); extern int __rio_local_write_config_8(struct rio_mport *port, u32 offset, u8 data); extern int rio_mport_read_config_32(struct rio_mport *port, u16 destid, - u8 hopcount, u32 offset, u32 * data); + u8 hopcount, u32 offset, u32 *data); extern int rio_mport_write_config_32(struct rio_mport *port, u16 destid, u8 hopcount, u32 offset, u32 data); extern int rio_mport_read_config_16(struct rio_mport *port, u16 destid, - u8 hopcount, u32 offset, u16 * data); + u8 hopcount, u32 offset, u16 *data); extern int rio_mport_write_config_16(struct rio_mport *port, u16 destid, u8 hopcount, u32 offset, u16 data); extern int rio_mport_read_config_8(struct rio_mport *port, u16 destid, - u8 hopcount, u32 offset, u8 * data); + u8 hopcount, u32 offset, u8 *data); extern int rio_mport_write_config_8(struct rio_mport *port, u16 destid, u8 hopcount, u32 offset, u8 data); @@ -56,7 +56,7 @@ extern int rio_mport_write_config_8(struct rio_mport *port, u16 destid, * device's configuration space. */ static inline int rio_local_read_config_32(struct rio_mport *port, u32 offset, - u32 * data) + u32 *data) { return __rio_local_read_config_32(port, offset, data); } @@ -86,7 +86,7 @@ static inline int rio_local_write_config_32(struct rio_mport *port, u32 offset, * device's configuration space. */ static inline int rio_local_read_config_16(struct rio_mport *port, u32 offset, - u16 * data) + u16 *data) { return __rio_local_read_config_16(port, offset, data); } @@ -117,7 +117,7 @@ static inline int rio_local_write_config_16(struct rio_mport *port, u32 offset, * device's configuration space. */ static inline int rio_local_read_config_8(struct rio_mport *port, u32 offset, - u8 * data) + u8 *data) { return __rio_local_read_config_8(port, offset, data); } @@ -147,10 +147,13 @@ static inline int rio_local_write_config_8(struct rio_mport *port, u32 offset, * RIO device's configuration space. */ static inline int rio_read_config_32(struct rio_dev *rdev, u32 offset, - u32 * data) + u32 *data) { - return rio_mport_read_config_32(rdev->net->hport, rdev->destid, - rdev->hopcount, offset, data); + if (likely(rdev->destid != rdev->hport->host_deviceid)) + return rio_mport_read_config_32(rdev->hport, rdev->destid, + rdev->hopcount, offset, data); + else + return rio_local_read_config_32(rdev->hport, offset, data); }; /** @@ -165,8 +168,11 @@ static inline int rio_read_config_32(struct rio_dev *rdev, u32 offset, static inline int rio_write_config_32(struct rio_dev *rdev, u32 offset, u32 data) { - return rio_mport_write_config_32(rdev->net->hport, rdev->destid, - rdev->hopcount, offset, data); + if (likely(rdev->destid != rdev->hport->host_deviceid)) + return rio_mport_write_config_32(rdev->hport, rdev->destid, + rdev->hopcount, offset, data); + else + return rio_local_write_config_32(rdev->hport, offset, data); }; /** @@ -179,10 +185,13 @@ static inline int rio_write_config_32(struct rio_dev *rdev, u32 offset, * RIO device's configuration space. */ static inline int rio_read_config_16(struct rio_dev *rdev, u32 offset, - u16 * data) + u16 *data) { - return rio_mport_read_config_16(rdev->net->hport, rdev->destid, - rdev->hopcount, offset, data); + if (likely(rdev->destid != rdev->hport->host_deviceid)) + return rio_mport_read_config_16(rdev->hport, rdev->destid, + rdev->hopcount, offset, data); + else + return rio_local_read_config_16(rdev->hport, offset, data); }; /** @@ -197,8 +206,11 @@ static inline int rio_read_config_16(struct rio_dev *rdev, u32 offset, static inline int rio_write_config_16(struct rio_dev *rdev, u32 offset, u16 data) { - return rio_mport_write_config_16(rdev->net->hport, rdev->destid, - rdev->hopcount, offset, data); + if (likely(rdev->destid != rdev->hport->host_deviceid)) + return rio_mport_write_config_16(rdev->hport, rdev->destid, + rdev->hopcount, offset, data); + else + return rio_local_write_config_16(rdev->hport, offset, data); }; /** @@ -210,10 +222,13 @@ static inline int rio_write_config_16(struct rio_dev *rdev, u32 offset, * Reads 8 bits of data from the specified offset within the * RIO device's configuration space. */ -static inline int rio_read_config_8(struct rio_dev *rdev, u32 offset, u8 * data) +static inline int rio_read_config_8(struct rio_dev *rdev, u32 offset, u8 *data) { - return rio_mport_read_config_8(rdev->net->hport, rdev->destid, - rdev->hopcount, offset, data); + if (likely(rdev->destid != rdev->hport->host_deviceid)) + return rio_mport_read_config_8(rdev->hport, rdev->destid, + rdev->hopcount, offset, data); + else + return rio_local_read_config_8(rdev->hport, offset, data); }; /** @@ -227,8 +242,11 @@ static inline int rio_read_config_8(struct rio_dev *rdev, u32 offset, u8 * data) */ static inline int rio_write_config_8(struct rio_dev *rdev, u32 offset, u8 data) { - return rio_mport_write_config_8(rdev->net->hport, rdev->destid, - rdev->hopcount, offset, data); + if (likely(rdev->destid != rdev->hport->host_deviceid)) + return rio_mport_write_config_8(rdev->hport, rdev->destid, + rdev->hopcount, offset, data); + else + return rio_local_write_config_8(rdev->hport, offset, data); }; extern int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, @@ -244,7 +262,7 @@ extern int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, */ static inline int rio_send_doorbell(struct rio_dev *rdev, u16 data) { - return rio_mport_send_doorbell(rdev->net->hport, rdev->destid, data); + return rio_mport_send_doorbell(rdev->hport, rdev->destid, data); }; /** @@ -292,13 +310,13 @@ static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end) * specific device. The assembly vendor and assembly device fields * will be set to %RIO_ANY_ID. */ -#define RIO_DEVICE(dev,ven) \ +#define RIO_DEVICE(dev, ven) \ .did = (dev), .vid = (ven), \ .asm_did = RIO_ANY_ID, .asm_vid = RIO_ANY_ID /* Mailbox management */ -extern int rio_request_outb_mbox(struct rio_mport *, void *, int, int, - void (*)(struct rio_mport *, void *,int, int)); +extern int rio_request_outb_mbox(struct rio_mport *, void *, int, int, int, + void (*)(struct rio_mport *, void *, int, int, void *)); extern int rio_release_outb_mbox(struct rio_mport *, int); /** @@ -313,15 +331,18 @@ extern int rio_release_outb_mbox(struct rio_mport *, int); * transmission. Returns 0 on success. */ static inline int rio_add_outb_message(struct rio_mport *mport, - struct rio_dev *rdev, int mbox, - void *buffer, size_t len) + struct rio_dev *rdev, + int mbox_dest, int letter, int flags, + void *buffer, size_t len, + void *cookie) { - return mport->ops->add_outb_message(mport, rdev, mbox, - buffer, len); + return mport->ops->add_outb_message(mport, rdev, + mbox_dest, letter, flags, + buffer, len, cookie); } extern int rio_request_inb_mbox(struct rio_mport *, void *, int, int, - void (*)(struct rio_mport *, void *, int, int)); + void (*)(struct rio_mport *, void *, int, int)); extern int rio_release_inb_mbox(struct rio_mport *, int); /** @@ -346,30 +367,33 @@ static inline int rio_add_inb_buffer(struct rio_mport *mport, int mbox, * * Get a RIO message from an inbound mailbox queue. Returns 0 on success. */ -static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox) +static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox, + int letter, int *sz, int *slot, u16 *destid) { - return mport->ops->get_inb_message(mport, mbox); + return mport->ops->get_inb_message(mport, mbox, letter, \ + sz, slot, destid); } /* Doorbell management */ extern int rio_request_inb_dbell(struct rio_mport *, void *, u16, u16, - void (*)(struct rio_mport *, void *, u16, u16, u16)); + void (*)(struct rio_mport *, void *, u16, u16, u16)); extern int rio_release_inb_dbell(struct rio_mport *, u16, u16); extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16); extern int rio_release_outb_dbell(struct rio_dev *, struct resource *); -/* Memory region management */ -int rio_claim_resource(struct rio_dev *, int); -int rio_request_regions(struct rio_dev *, char *); -void rio_release_regions(struct rio_dev *); -int rio_request_region(struct rio_dev *, int, char *); -void rio_release_region(struct rio_dev *, int); +/* Memory low-level mapping functions */ +extern int rio_req_outb_region(struct rio_mport *, resource_size_t, + const char *, u32, u32*); +extern int rio_map_outb_mem(struct rio_mport *, + u32, u16, u32, u32, struct rio_map_addr*); +extern void rio_release_outb_region(struct rio_mport *, u32); /* Port-Write management */ extern int rio_request_inb_pwrite(struct rio_dev *, int (*)(struct rio_dev *, union rio_pw_msg*, int)); extern int rio_release_inb_pwrite(struct rio_dev *); -extern int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg); +extern int rio_inb_pwrite_handler(struct rio_mport *mport, \ + union rio_pw_msg *pw_msg); /* LDM support */ int rio_register_driver(struct rio_driver *); @@ -419,5 +443,97 @@ extern u16 rio_local_get_device_id(struct rio_mport *port); extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from); extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did, struct rio_dev *from); +extern struct rio_mport *rio_get_mport(int hostid, struct rio_mport *from); +extern struct rio_dev **rio_get_all_devices(struct rio_mport *mport, int *n); +extern struct rio_dev *lookup_rdev(struct rio_mport *mport, u16 destid); +#define RIO_JOB_FLAG_STATIC 0x1 + +extern int rio_job_init(struct rio_mport *mport, struct rio_dev *rdev, + int port, u32 flags, int hw_access, int event); +extern struct rio_dev *rio_get_root_node(struct rio_mport *mport); +extern int rio_lookup_next_destid(struct rio_mport *mport, u16 parent_destid, + int port_num, u8 hopcount, u16 *id); + +#if defined(CONFIG_RAPIDIO_HOTPLUG) + +extern void rio_rescan_mport(struct rio_mport *mport); +extern void rio_remove_mport_net(struct rio_mport *mport, int hw_access); + +static inline int rio_hotswap(struct rio_mport *mport, u8 flags) +{ + if (mport->ops->hotswap) + return mport->ops->hotswap(mport, flags); + else + return -EINVAL; +} +static inline int rio_request_mport_cb(struct rio_mport *mport, + int enable, + void (*cb)(struct rio_mport *mport)) +{ + if (mport->ops->port_notify_cb) + return mport->ops->port_notify_cb(mport, enable, cb); + else + return -EINVAL; +} +#define MPORT_STATE_OPERATIONAL 0 +#define MPORT_STATE_DOWN 1 +#define MPORT_STATE_UNKNOWN 3 +static inline int rio_port_op_state(struct rio_mport *mport) +{ + if (mport->ops->port_op_state) + return mport->ops->port_op_state(mport); + else + return MPORT_STATE_UNKNOWN; +} + +extern int rio_setup_event(struct rio_dev *rdev, int portnum, int event); +extern int rio_setup_event_force(struct rio_dev *rdev, int portnum, int event); + +#endif + +#ifdef CONFIG_RAPIDIO_STATIC_DESTID +extern int rio_add_netid(u16 mport_destid, int net_id, int comptag); + +extern int rio_add_destid(struct rio_mport *mport, + u16 parent_destid, int parent_port, + int hopcount, u16 destid, u16 comptag); +extern int rio_block_destid_route(struct rio_mport *mport, + u16 parent_destid, int parent_port, + int hopcount, u16 destid, u16 comptag); +extern int rio_split_destid_route(struct rio_mport *mport, u16 parent_destid, + int parent_port, int hopcount, u16 destid, + u16 comptag, u8 return_port); +extern int rio_legacy_destid_route(struct rio_mport *mport, + u16 parent_destid, int parent_port, + int hopcount, u16 destid, u16 comptag, + u8 lock_hw, u8 lut_update); +extern void rio_release_destid(struct rio_mport *mport, u16 parent_destid, + int parent_port, int hopcount); +extern int rio_add_static_route(struct rio_mport *mport, u16 parent_destid, + int parent_port, int hopcount, + struct rio_static_route *route, int num_routes); +extern int rio_update_static_route(struct rio_mport *mport, u16 parent_destid, + int parent_port, int hopcount, + struct rio_static_route *route, int num_routes); +extern int rio_remove_static_route(struct rio_mport *mport, u16 parent_destid, + int parent_port, int hopcount, + struct rio_static_route *route, int num_routes); +extern int rio_lookup_static_routes(struct rio_mport *mport, u16 parent_destid, + int parent_port, int hopcount, + struct rio_static_route *sroute, int num_routes); +extern struct rio_static_route *rio_static_route_table(struct rio_mport *mport, + u16 parent_destid, + int parent_port, + int hopcount, + u16 *destid, + int *n); +extern int rio_remove_netid(u16 mport_destid, int net_id); +extern int rio_find_netid(u16 mport_destid, int *net_id); +extern int rio_release_node_table(struct rio_mport *mport); +#endif + +#if defined(CONFIG_RAPIDIO_HOTPLUG) || defined(CONFIG_RAPIDIO_STATIC_DESTID) +extern ssize_t rio_net_nodes_show(struct rio_mport *mport, char *buf); +#endif #endif /* LINUX_RIO_DRV_H */ diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h index b66d13d..ffca266 100644 --- a/include/linux/rio_ids.h +++ b/include/linux/rio_ids.h @@ -40,5 +40,12 @@ #define RIO_DID_IDTVPS1616 0x0377 #define RIO_DID_IDTSPS1616 0x0378 #define RIO_DID_TSI721 0x80ab +#define RIO_VID_JENNIC 0x005a +#define RIO_DID_ERICSSON_ULMA 0x0000 +#define RIO_DID_ERICSSON_MERCURY 0x0006 +#define RIO_DID_ERICSSON_HERMES 0x0007 +#define RIO_VID_TEXAS 0x0030 +#define RIO_DID_TEXAS_TCI6616 0xb941 +#define RIO_DID_TEXAS_TCI6616X 0x009d #endif /* LINUX_RIO_IDS_H */ diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h index 218168a..d178b9b 100644 --- a/include/linux/rio_regs.h +++ b/include/linux/rio_regs.h @@ -42,8 +42,13 @@ #define RIO_PEF_INB_MBOX2 0x00200000 /* [II, <= 1.2] Mailbox 2 */ #define RIO_PEF_INB_MBOX3 0x00100000 /* [II, <= 1.2] Mailbox 3 */ #define RIO_PEF_INB_DOORBELL 0x00080000 /* [II, <= 1.2] Doorbells */ +#define RIO_PEF_FLOW_ARB 0x00000800 /* [III] Flow Arbitration support */ +#define RIO_PEF_MCAST 0x00000400 /* [III] Multicast support */ #define RIO_PEF_EXT_RT 0x00000200 /* [III, 1.3] Extended route table support */ #define RIO_PEF_STD_RT 0x00000100 /* [III, 1.3] Standard route table support */ +#define RIO_PEF_FCS 0x00000080 /* [III] Flow Control Support */ +#define RIO_PEF_CRC_ERR_REC 0x00000040 /* [III] CRC Error Recovery */ +#define RIO_PEF_CRFS 0x00000020 /* [III] Critical Request Flow Supt */ #define RIO_PEF_CTLS 0x00000010 /* [III] CTLS */ #define RIO_PEF_EXT_FEATURES 0x00000008 /* [I] EFT_PTR valid */ #define RIO_PEF_ADDR_66 0x00000004 /* [I] 66 bits */ @@ -167,6 +172,25 @@ #define RIO_STD_RTE_CONF_PORT_SEL_CSR 0x74 #define RIO_STD_RTE_DEFAULT_PORT 0x78 +#define RIO_MCAST_MASK_PORT_CSR 0x80 /* Multicast Mask Port CSR */ +#define RIO_MCAST_MASK(x) ((x) << 16) /* Multicast Mask */ +#define RIO_EGRESS_PORT_NUMBER(x) ((x) << 8) /* Port Number */ +#define RIO_MASK_CMD_ADD_PORT (0x1 << 4) /* Add Port Command */ +#define RIO_MASK_CMD_DEL_PORT (0x2 << 4) /* Delete Port Command */ +#define RIO_MASK_CMD_DEL_ALL_PORTS (0x4 << 4) /* Delete All Ports Cmd */ +#define RIO_MASK_CMD_ADD_ALL_PORTS (0x5 << 4) /* Add All Ports Cmd */ +#define RIO_MCAST_PORT_PRESENT (0x00000001) /* Port Present from Write + to Verify command */ + +#define RIO_MCAST_ASSOC_SEL_CSR 0x84 /* Multicast Assoc Select CSR */ +#define RIO_MCAST_LARGE_DEST_ID(x) ((x) << 24) /* Large Destination Id */ +#define RIO_MCAST_DEST_ID(x) ((x) << 16) /* Destination Id */ +#define RIO_MCAST_MASK_NO(x) (x) /* Multicast Mask # */ + +#define RIO_MCAST_ASSOC_OP_CSR 0x88 /* Multicast Assoc Operation CSR */ +#define RIO_MCAST_TRANS_ASSOC(x) ((x) << 7) /* Transport Association */ +#define RIO_MCAST_DEL_ASSOC (0x1 << 5) /* Delete Association */ +#define RIO_MCAST_ADD_ASSOC (0x3 << 5) /* Add Association */ /* 0x7c-0xf8 *//* Reserved */ /* 0x100-0xfff8 *//* [I] Extended Features Space */ /* 0x10000-0xfffff8 *//* [I] Implementation-defined Space */ @@ -251,10 +275,12 @@ #define RIO_PORT_N_CTL_PWIDTH_4 0x40000000 #define RIO_PORT_N_CTL_P_TYP_SER 0x00000001 #define RIO_PORT_N_CTL_LOCKOUT 0x00000002 +#define RIO_PORT_N_CTL_PORT_DIS 0x00800000 #define RIO_PORT_N_CTL_EN_RX_SER 0x00200000 #define RIO_PORT_N_CTL_EN_TX_SER 0x00400000 #define RIO_PORT_N_CTL_EN_RX_PAR 0x08000000 #define RIO_PORT_N_CTL_EN_TX_PAR 0x40000000 +#define RIO_PORT_N_CTL_ENUM_BOUNDARY 0x00020000 /* * Error Management Extensions (RapidIO 1.3+, Part 8) diff --git a/include/linux/riopw.h b/include/linux/riopw.h new file mode 100644 index 0000000..ec7ef76f --- /dev/null +++ b/include/linux/riopw.h @@ -0,0 +1,30 @@ +#ifndef _RIOPW_H_ +#define _RIOPW_H_ + +#define RIOPW_IOC_MAGIC 'j' /* Arbitrary */ +#define RIOPW_IOC_MINNR 0x40 +#define RIOPW_IOC_MAXNR 0x80 + +#define IOCTL_MPORT_GETHID _IOR(RIOPW_IOC_MAGIC, 0x40, int) +#define IOCTL_MPORT_GETPWMSG _IOR(RIOPW_IOC_MAGIC, 0x45, int) + +#ifdef __KERNEL__ +#else + +#define RIO_PW_MSG_SIZE 64 + +union rio_pw_msg { + struct { + unsigned int comptag; /* Component Tag CSR */ + unsigned int errdetect; /* Port N Error Detect CSR */ + unsigned int is_port; /* Implementation specific + PortID */ + unsigned int ltlerrdet; /* LTL Error Detect CSR */ + unsigned int padding[12]; + } em; + unsigned int raw[RIO_PW_MSG_SIZE/sizeof(unsigned int)]; +}; + +#endif + + +#endif -- 1.7.9.5 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto