diff options
author | Geoff Levand <geoffrey.levand@am.sony.com> | 2007-06-15 17:52:02 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-06-28 05:16:38 -0400 |
commit | 6bb5cf1025414fe00b20f3bef56135849e4ed3b8 (patch) | |
tree | d8cc37288ce123dc790af37f99b7bcc7c9e1872d /include/asm-powerpc | |
parent | 9263e85aa9e9d341ef238fffc040f586674d1709 (diff) |
[POWERPC] PS3: System-bus rework
Rework the PS3 system bus to unify device support.
- DMA region sizes must be a power of two
- storage bus DMA updates:
- Small fixes for the PS3 DMA core:
o fix alignment bug
o kill superfluous test
o indentation
o spelling
o export ps3_dma_region_{create,free}()
- ps3_dma_region_init():
o Add `addr' and `len' parameters, so you can create a DMA region that
does not cover all memory (use `NULL' and `0' to cover all memory).
This is needed because there are not sufficient IOMMU resources to have
all DMA regions cover all memory.
o Uninline
- Added remove and shutdown routines to all drivers.
- Added loadable module support to all drivers.
- Added HV calls for iopte management (needed by sound driver).
Signed-off-by: MOKUNO Masakazu <mokuno@sm.sony.co.jp>
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r-- | include/asm-powerpc/lv1call.h | 3 | ||||
-rw-r--r-- | include/asm-powerpc/ps3.h | 148 |
2 files changed, 101 insertions, 50 deletions
diff --git a/include/asm-powerpc/lv1call.h b/include/asm-powerpc/lv1call.h index f733beeea63a..81713acf7529 100644 --- a/include/asm-powerpc/lv1call.h +++ b/include/asm-powerpc/lv1call.h | |||
@@ -238,6 +238,7 @@ LV1_CALL(destruct_virtual_address_space, 1, 0, 10 ) | |||
238 | LV1_CALL(configure_irq_state_bitmap, 3, 0, 11 ) | 238 | LV1_CALL(configure_irq_state_bitmap, 3, 0, 11 ) |
239 | LV1_CALL(connect_irq_plug_ext, 5, 0, 12 ) | 239 | LV1_CALL(connect_irq_plug_ext, 5, 0, 12 ) |
240 | LV1_CALL(release_memory, 1, 0, 13 ) | 240 | LV1_CALL(release_memory, 1, 0, 13 ) |
241 | LV1_CALL(put_iopte, 5, 0, 15 ) | ||
241 | LV1_CALL(disconnect_irq_plug_ext, 3, 0, 17 ) | 242 | LV1_CALL(disconnect_irq_plug_ext, 3, 0, 17 ) |
242 | LV1_CALL(construct_event_receive_port, 0, 1, 18 ) | 243 | LV1_CALL(construct_event_receive_port, 0, 1, 18 ) |
243 | LV1_CALL(destruct_event_receive_port, 1, 0, 19 ) | 244 | LV1_CALL(destruct_event_receive_port, 1, 0, 19 ) |
@@ -268,6 +269,8 @@ LV1_CALL(remove_repository_node, 4, 0, 93 ) | |||
268 | LV1_CALL(read_htab_entries, 2, 5, 95 ) | 269 | LV1_CALL(read_htab_entries, 2, 5, 95 ) |
269 | LV1_CALL(set_dabr, 2, 0, 96 ) | 270 | LV1_CALL(set_dabr, 2, 0, 96 ) |
270 | LV1_CALL(get_total_execution_time, 2, 1, 103 ) | 271 | LV1_CALL(get_total_execution_time, 2, 1, 103 ) |
272 | LV1_CALL(allocate_io_segment, 3, 1, 116 ) | ||
273 | LV1_CALL(release_io_segment, 2, 0, 117 ) | ||
271 | LV1_CALL(construct_io_irq_outlet, 1, 1, 120 ) | 274 | LV1_CALL(construct_io_irq_outlet, 1, 1, 120 ) |
272 | LV1_CALL(destruct_io_irq_outlet, 1, 0, 121 ) | 275 | LV1_CALL(destruct_io_irq_outlet, 1, 0, 121 ) |
273 | LV1_CALL(map_htab, 1, 1, 122 ) | 276 | LV1_CALL(map_htab, 1, 1, 122 ) |
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h index ac85d729f14f..4f753907bbf9 100644 --- a/include/asm-powerpc/ps3.h +++ b/include/asm-powerpc/ps3.h | |||
@@ -49,18 +49,6 @@ enum ps3_param_av_multi_out { | |||
49 | 49 | ||
50 | enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void); | 50 | enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void); |
51 | 51 | ||
52 | /** | ||
53 | * struct ps3_device_id - HV bus device identifier from the system repository | ||
54 | * @bus_id: HV bus id, {1..} (zero invalid) | ||
55 | * @dev_id: HV device id, {0..} | ||
56 | */ | ||
57 | |||
58 | struct ps3_device_id { | ||
59 | unsigned int bus_id; | ||
60 | unsigned int dev_id; | ||
61 | }; | ||
62 | |||
63 | |||
64 | /* dma routines */ | 52 | /* dma routines */ |
65 | 53 | ||
66 | enum ps3_dma_page_size { | 54 | enum ps3_dma_page_size { |
@@ -75,6 +63,8 @@ enum ps3_dma_region_type { | |||
75 | PS3_DMA_INTERNAL = 2, | 63 | PS3_DMA_INTERNAL = 2, |
76 | }; | 64 | }; |
77 | 65 | ||
66 | struct ps3_dma_region_ops; | ||
67 | |||
78 | /** | 68 | /** |
79 | * struct ps3_dma_region - A per device dma state variables structure | 69 | * struct ps3_dma_region - A per device dma state variables structure |
80 | * @did: The HV device id. | 70 | * @did: The HV device id. |
@@ -82,21 +72,42 @@ enum ps3_dma_region_type { | |||
82 | * @region_type: The HV region type. | 72 | * @region_type: The HV region type. |
83 | * @bus_addr: The 'translated' bus address of the region. | 73 | * @bus_addr: The 'translated' bus address of the region. |
84 | * @len: The length in bytes of the region. | 74 | * @len: The length in bytes of the region. |
75 | * @offset: The offset from the start of memory of the region. | ||
76 | * @ioid: The IOID of the device who owns this region | ||
85 | * @chunk_list: Opaque variable used by the ioc page manager. | 77 | * @chunk_list: Opaque variable used by the ioc page manager. |
78 | * @region_ops: struct ps3_dma_region_ops - dma region operations | ||
86 | */ | 79 | */ |
87 | 80 | ||
88 | struct ps3_dma_region { | 81 | struct ps3_dma_region { |
89 | struct ps3_device_id did; | 82 | struct ps3_system_bus_device *dev; |
83 | /* device variables */ | ||
84 | const struct ps3_dma_region_ops *region_ops; | ||
85 | unsigned char ioid; | ||
90 | enum ps3_dma_page_size page_size; | 86 | enum ps3_dma_page_size page_size; |
91 | enum ps3_dma_region_type region_type; | 87 | enum ps3_dma_region_type region_type; |
92 | unsigned long bus_addr; | ||
93 | unsigned long len; | 88 | unsigned long len; |
89 | unsigned long offset; | ||
90 | |||
91 | /* driver variables (set by ps3_dma_region_create) */ | ||
92 | unsigned long bus_addr; | ||
94 | struct { | 93 | struct { |
95 | spinlock_t lock; | 94 | spinlock_t lock; |
96 | struct list_head head; | 95 | struct list_head head; |
97 | } chunk_list; | 96 | } chunk_list; |
98 | }; | 97 | }; |
99 | 98 | ||
99 | struct ps3_dma_region_ops { | ||
100 | int (*create)(struct ps3_dma_region *); | ||
101 | int (*free)(struct ps3_dma_region *); | ||
102 | int (*map)(struct ps3_dma_region *, | ||
103 | unsigned long virt_addr, | ||
104 | unsigned long len, | ||
105 | unsigned long *bus_addr, | ||
106 | u64 iopte_pp); | ||
107 | int (*unmap)(struct ps3_dma_region *, | ||
108 | unsigned long bus_addr, | ||
109 | unsigned long len); | ||
110 | }; | ||
100 | /** | 111 | /** |
101 | * struct ps3_dma_region_init - Helper to initialize structure variables | 112 | * struct ps3_dma_region_init - Helper to initialize structure variables |
102 | * | 113 | * |
@@ -104,18 +115,16 @@ struct ps3_dma_region { | |||
104 | * ps3_system_bus_device_register. | 115 | * ps3_system_bus_device_register. |
105 | */ | 116 | */ |
106 | 117 | ||
107 | static inline void ps3_dma_region_init(struct ps3_dma_region *r, | 118 | struct ps3_system_bus_device; |
108 | const struct ps3_device_id* did, enum ps3_dma_page_size page_size, | 119 | |
109 | enum ps3_dma_region_type region_type) | 120 | int ps3_dma_region_init(struct ps3_system_bus_device *dev, |
110 | { | 121 | struct ps3_dma_region *r, enum ps3_dma_page_size page_size, |
111 | r->did = *did; | 122 | enum ps3_dma_region_type region_type, void *addr, unsigned long len); |
112 | r->page_size = page_size; | ||
113 | r->region_type = region_type; | ||
114 | } | ||
115 | int ps3_dma_region_create(struct ps3_dma_region *r); | 123 | int ps3_dma_region_create(struct ps3_dma_region *r); |
116 | int ps3_dma_region_free(struct ps3_dma_region *r); | 124 | int ps3_dma_region_free(struct ps3_dma_region *r); |
117 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, | 125 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, |
118 | unsigned long len, unsigned long *bus_addr); | 126 | unsigned long len, unsigned long *bus_addr, |
127 | u64 iopte_pp); | ||
119 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, | 128 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, |
120 | unsigned long len); | 129 | unsigned long len); |
121 | 130 | ||
@@ -126,6 +135,7 @@ enum ps3_mmio_page_size { | |||
126 | PS3_MMIO_64K = 16U | 135 | PS3_MMIO_64K = 16U |
127 | }; | 136 | }; |
128 | 137 | ||
138 | struct ps3_mmio_region_ops; | ||
129 | /** | 139 | /** |
130 | * struct ps3_mmio_region - a per device mmio state variables structure | 140 | * struct ps3_mmio_region - a per device mmio state variables structure |
131 | * | 141 | * |
@@ -133,13 +143,18 @@ enum ps3_mmio_page_size { | |||
133 | */ | 143 | */ |
134 | 144 | ||
135 | struct ps3_mmio_region { | 145 | struct ps3_mmio_region { |
136 | struct ps3_device_id did; | 146 | struct ps3_system_bus_device *dev; |
147 | const struct ps3_mmio_region_ops *mmio_ops; | ||
137 | unsigned long bus_addr; | 148 | unsigned long bus_addr; |
138 | unsigned long len; | 149 | unsigned long len; |
139 | enum ps3_mmio_page_size page_size; | 150 | enum ps3_mmio_page_size page_size; |
140 | unsigned long lpar_addr; | 151 | unsigned long lpar_addr; |
141 | }; | 152 | }; |
142 | 153 | ||
154 | struct ps3_mmio_region_ops { | ||
155 | int (*create)(struct ps3_mmio_region *); | ||
156 | int (*free)(struct ps3_mmio_region *); | ||
157 | }; | ||
143 | /** | 158 | /** |
144 | * struct ps3_mmio_region_init - Helper to initialize structure variables | 159 | * struct ps3_mmio_region_init - Helper to initialize structure variables |
145 | * | 160 | * |
@@ -147,15 +162,9 @@ struct ps3_mmio_region { | |||
147 | * ps3_system_bus_device_register. | 162 | * ps3_system_bus_device_register. |
148 | */ | 163 | */ |
149 | 164 | ||
150 | static inline void ps3_mmio_region_init(struct ps3_mmio_region *r, | 165 | int ps3_mmio_region_init(struct ps3_system_bus_device *dev, |
151 | const struct ps3_device_id* did, unsigned long bus_addr, | 166 | struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, |
152 | unsigned long len, enum ps3_mmio_page_size page_size) | 167 | enum ps3_mmio_page_size page_size); |
153 | { | ||
154 | r->did = *did; | ||
155 | r->bus_addr = bus_addr; | ||
156 | r->len = len; | ||
157 | r->page_size = page_size; | ||
158 | } | ||
159 | int ps3_mmio_region_create(struct ps3_mmio_region *r); | 168 | int ps3_mmio_region_create(struct ps3_mmio_region *r); |
160 | int ps3_free_mmio_region(struct ps3_mmio_region *r); | 169 | int ps3_free_mmio_region(struct ps3_mmio_region *r); |
161 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr); | 170 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr); |
@@ -188,11 +197,10 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, | |||
188 | unsigned int class, unsigned int *virq); | 197 | unsigned int class, unsigned int *virq); |
189 | int ps3_spe_irq_destroy(unsigned int virq); | 198 | int ps3_spe_irq_destroy(unsigned int virq); |
190 | 199 | ||
191 | int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, | 200 | int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, |
192 | const struct ps3_device_id *did, unsigned int interrupt_id, | 201 | enum ps3_cpu_binding cpu, unsigned int *virq); |
193 | unsigned int *virq); | 202 | int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, |
194 | int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, | 203 | unsigned int virq); |
195 | unsigned int interrupt_id, unsigned int virq); | ||
196 | 204 | ||
197 | /* lv1 result codes */ | 205 | /* lv1 result codes */ |
198 | 206 | ||
@@ -290,11 +298,33 @@ static inline const char* ps3_result(int result) | |||
290 | /* system bus routines */ | 298 | /* system bus routines */ |
291 | 299 | ||
292 | enum ps3_match_id { | 300 | enum ps3_match_id { |
293 | PS3_MATCH_ID_EHCI = 1, | 301 | PS3_MATCH_ID_EHCI = 1, |
294 | PS3_MATCH_ID_OHCI, | 302 | PS3_MATCH_ID_OHCI = 2, |
295 | PS3_MATCH_ID_GELIC, | 303 | PS3_MATCH_ID_GELIC = 3, |
296 | PS3_MATCH_ID_AV_SETTINGS, | 304 | PS3_MATCH_ID_AV_SETTINGS = 4, |
297 | PS3_MATCH_ID_SYSTEM_MANAGER, | 305 | PS3_MATCH_ID_SYSTEM_MANAGER = 5, |
306 | PS3_MATCH_ID_STOR_DISK = 6, | ||
307 | PS3_MATCH_ID_STOR_ROM = 7, | ||
308 | PS3_MATCH_ID_STOR_FLASH = 8, | ||
309 | PS3_MATCH_ID_SOUND = 9, | ||
310 | PS3_MATCH_ID_GRAPHICS = 10, | ||
311 | }; | ||
312 | |||
313 | #define PS3_MODULE_ALIAS_EHCI "ps3:1" | ||
314 | #define PS3_MODULE_ALIAS_OHCI "ps3:2" | ||
315 | #define PS3_MODULE_ALIAS_GELIC "ps3:3" | ||
316 | #define PS3_MODULE_ALIAS_AV_SETTINGS "ps3:4" | ||
317 | #define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5" | ||
318 | #define PS3_MODULE_ALIAS_STOR_DISK "ps3:6" | ||
319 | #define PS3_MODULE_ALIAS_STOR_ROM "ps3:7" | ||
320 | #define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8" | ||
321 | #define PS3_MODULE_ALIAS_SOUND "ps3:9" | ||
322 | #define PS3_MODULE_ALIAS_GRAPHICS "ps3:10" | ||
323 | |||
324 | enum ps3_system_bus_device_type { | ||
325 | PS3_DEVICE_TYPE_IOC0 = 1, | ||
326 | PS3_DEVICE_TYPE_SB, | ||
327 | PS3_DEVICE_TYPE_VUART, | ||
298 | }; | 328 | }; |
299 | 329 | ||
300 | /** | 330 | /** |
@@ -303,14 +333,23 @@ enum ps3_match_id { | |||
303 | 333 | ||
304 | struct ps3_system_bus_device { | 334 | struct ps3_system_bus_device { |
305 | enum ps3_match_id match_id; | 335 | enum ps3_match_id match_id; |
306 | struct ps3_device_id did; | 336 | enum ps3_system_bus_device_type dev_type; |
307 | unsigned int interrupt_id; | 337 | |
308 | /* struct iommu_table *iommu_table; -- waiting for Ben's cleanups */ | 338 | unsigned int bus_id; /* SB */ |
309 | struct ps3_dma_region *d_region; | 339 | unsigned int dev_id; /* SB */ |
310 | struct ps3_mmio_region *m_region; | 340 | unsigned int interrupt_id; /* SB */ |
341 | struct ps3_dma_region *d_region; /* SB, IOC0 */ | ||
342 | struct ps3_mmio_region *m_region; /* SB, IOC0*/ | ||
343 | unsigned int port_number; /* VUART */ | ||
344 | |||
345 | /* struct iommu_table *iommu_table; -- waiting for BenH's cleanups */ | ||
311 | struct device core; | 346 | struct device core; |
347 | void *driver_priv; /* private driver variables */ | ||
312 | }; | 348 | }; |
313 | 349 | ||
350 | int ps3_open_hv_device(struct ps3_system_bus_device *dev); | ||
351 | int ps3_close_hv_device(struct ps3_system_bus_device *dev); | ||
352 | |||
314 | /** | 353 | /** |
315 | * struct ps3_system_bus_driver - a driver for a device on the system bus | 354 | * struct ps3_system_bus_driver - a driver for a device on the system bus |
316 | */ | 355 | */ |
@@ -320,6 +359,7 @@ struct ps3_system_bus_driver { | |||
320 | struct device_driver core; | 359 | struct device_driver core; |
321 | int (*probe)(struct ps3_system_bus_device *); | 360 | int (*probe)(struct ps3_system_bus_device *); |
322 | int (*remove)(struct ps3_system_bus_device *); | 361 | int (*remove)(struct ps3_system_bus_device *); |
362 | int (*shutdown)(struct ps3_system_bus_device *); | ||
323 | /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ | 363 | /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ |
324 | /* int (*resume)(struct ps3_system_bus_device *); */ | 364 | /* int (*resume)(struct ps3_system_bus_device *); */ |
325 | }; | 365 | }; |
@@ -327,16 +367,24 @@ struct ps3_system_bus_driver { | |||
327 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev); | 367 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev); |
328 | int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv); | 368 | int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv); |
329 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv); | 369 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv); |
330 | static inline struct ps3_system_bus_driver *to_ps3_system_bus_driver( | 370 | |
371 | static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv( | ||
331 | struct device_driver *_drv) | 372 | struct device_driver *_drv) |
332 | { | 373 | { |
333 | return container_of(_drv, struct ps3_system_bus_driver, core); | 374 | return container_of(_drv, struct ps3_system_bus_driver, core); |
334 | } | 375 | } |
335 | static inline struct ps3_system_bus_device *to_ps3_system_bus_device( | 376 | static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev( |
336 | struct device *_dev) | 377 | struct device *_dev) |
337 | { | 378 | { |
338 | return container_of(_dev, struct ps3_system_bus_device, core); | 379 | return container_of(_dev, struct ps3_system_bus_device, core); |
339 | } | 380 | } |
381 | static inline struct ps3_system_bus_driver * | ||
382 | ps3_system_bus_dev_to_system_bus_drv(struct ps3_system_bus_device *_dev) | ||
383 | { | ||
384 | BUG_ON(!_dev); | ||
385 | BUG_ON(!_dev->core.driver); | ||
386 | return ps3_drv_to_system_bus_drv(_dev->core.driver); | ||
387 | } | ||
340 | 388 | ||
341 | /** | 389 | /** |
342 | * ps3_system_bus_set_drvdata - | 390 | * ps3_system_bus_set_drvdata - |