1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * cb710/cb710.h
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright by Michał Mirosław, 2008-2009
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun #ifndef LINUX_CB710_DRIVER_H
8*4882a593Smuzhiyun #define LINUX_CB710_DRIVER_H
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/io.h>
11*4882a593Smuzhiyun #include <linux/interrupt.h>
12*4882a593Smuzhiyun #include <linux/spinlock.h>
13*4882a593Smuzhiyun #include <linux/pci.h>
14*4882a593Smuzhiyun #include <linux/platform_device.h>
15*4882a593Smuzhiyun #include <linux/mmc/host.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun struct cb710_slot;
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun typedef int (*cb710_irq_handler_t)(struct cb710_slot *);
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /* per-virtual-slot structure */
22*4882a593Smuzhiyun struct cb710_slot {
23*4882a593Smuzhiyun struct platform_device pdev;
24*4882a593Smuzhiyun void __iomem *iobase;
25*4882a593Smuzhiyun cb710_irq_handler_t irq_handler;
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /* per-device structure */
29*4882a593Smuzhiyun struct cb710_chip {
30*4882a593Smuzhiyun struct pci_dev *pdev;
31*4882a593Smuzhiyun void __iomem *iobase;
32*4882a593Smuzhiyun unsigned platform_id;
33*4882a593Smuzhiyun #ifdef CONFIG_CB710_DEBUG_ASSUMPTIONS
34*4882a593Smuzhiyun atomic_t slot_refs_count;
35*4882a593Smuzhiyun #endif
36*4882a593Smuzhiyun unsigned slot_mask;
37*4882a593Smuzhiyun unsigned slots;
38*4882a593Smuzhiyun spinlock_t irq_lock;
39*4882a593Smuzhiyun struct cb710_slot slot[];
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* NOTE: cb710_chip.slots is modified only during device init/exit and
43*4882a593Smuzhiyun * they are all serialized wrt themselves */
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /* cb710_chip.slot_mask values */
46*4882a593Smuzhiyun #define CB710_SLOT_MMC 1
47*4882a593Smuzhiyun #define CB710_SLOT_MS 2
48*4882a593Smuzhiyun #define CB710_SLOT_SM 4
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* slot port accessors - so the logic is more clear in the code */
51*4882a593Smuzhiyun #define CB710_PORT_ACCESSORS(t) \
52*4882a593Smuzhiyun static inline void cb710_write_port_##t(struct cb710_slot *slot, \
53*4882a593Smuzhiyun unsigned port, u##t value) \
54*4882a593Smuzhiyun { \
55*4882a593Smuzhiyun iowrite##t(value, slot->iobase + port); \
56*4882a593Smuzhiyun } \
57*4882a593Smuzhiyun \
58*4882a593Smuzhiyun static inline u##t cb710_read_port_##t(struct cb710_slot *slot, \
59*4882a593Smuzhiyun unsigned port) \
60*4882a593Smuzhiyun { \
61*4882a593Smuzhiyun return ioread##t(slot->iobase + port); \
62*4882a593Smuzhiyun } \
63*4882a593Smuzhiyun \
64*4882a593Smuzhiyun static inline void cb710_modify_port_##t(struct cb710_slot *slot, \
65*4882a593Smuzhiyun unsigned port, u##t set, u##t clear) \
66*4882a593Smuzhiyun { \
67*4882a593Smuzhiyun iowrite##t( \
68*4882a593Smuzhiyun (ioread##t(slot->iobase + port) & ~clear)|set, \
69*4882a593Smuzhiyun slot->iobase + port); \
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun CB710_PORT_ACCESSORS(8)
73*4882a593Smuzhiyun CB710_PORT_ACCESSORS(16)
74*4882a593Smuzhiyun CB710_PORT_ACCESSORS(32)
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun void cb710_pci_update_config_reg(struct pci_dev *pdev,
77*4882a593Smuzhiyun int reg, uint32_t and, uint32_t xor);
78*4882a593Smuzhiyun void cb710_set_irq_handler(struct cb710_slot *slot,
79*4882a593Smuzhiyun cb710_irq_handler_t handler);
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /* some device struct walking */
82*4882a593Smuzhiyun
cb710_pdev_to_slot(struct platform_device * pdev)83*4882a593Smuzhiyun static inline struct cb710_slot *cb710_pdev_to_slot(
84*4882a593Smuzhiyun struct platform_device *pdev)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun return container_of(pdev, struct cb710_slot, pdev);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
cb710_slot_to_chip(struct cb710_slot * slot)89*4882a593Smuzhiyun static inline struct cb710_chip *cb710_slot_to_chip(struct cb710_slot *slot)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun return dev_get_drvdata(slot->pdev.dev.parent);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
cb710_slot_dev(struct cb710_slot * slot)94*4882a593Smuzhiyun static inline struct device *cb710_slot_dev(struct cb710_slot *slot)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun return &slot->pdev.dev;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
cb710_chip_dev(struct cb710_chip * chip)99*4882a593Smuzhiyun static inline struct device *cb710_chip_dev(struct cb710_chip *chip)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun return &chip->pdev->dev;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /* debugging aids */
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun #ifdef CONFIG_CB710_DEBUG
107*4882a593Smuzhiyun void cb710_dump_regs(struct cb710_chip *chip, unsigned dump);
108*4882a593Smuzhiyun #else
109*4882a593Smuzhiyun #define cb710_dump_regs(c, d) do {} while (0)
110*4882a593Smuzhiyun #endif
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun #define CB710_DUMP_REGS_MMC 0x0F
113*4882a593Smuzhiyun #define CB710_DUMP_REGS_MS 0x30
114*4882a593Smuzhiyun #define CB710_DUMP_REGS_SM 0xC0
115*4882a593Smuzhiyun #define CB710_DUMP_REGS_ALL 0xFF
116*4882a593Smuzhiyun #define CB710_DUMP_REGS_MASK 0xFF
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun #define CB710_DUMP_ACCESS_8 0x100
119*4882a593Smuzhiyun #define CB710_DUMP_ACCESS_16 0x200
120*4882a593Smuzhiyun #define CB710_DUMP_ACCESS_32 0x400
121*4882a593Smuzhiyun #define CB710_DUMP_ACCESS_ALL 0x700
122*4882a593Smuzhiyun #define CB710_DUMP_ACCESS_MASK 0x700
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun #endif /* LINUX_CB710_DRIVER_H */
125*4882a593Smuzhiyun /*
126*4882a593Smuzhiyun * cb710/sgbuf2.h
127*4882a593Smuzhiyun *
128*4882a593Smuzhiyun * Copyright by Michał Mirosław, 2008-2009
129*4882a593Smuzhiyun */
130*4882a593Smuzhiyun #ifndef LINUX_CB710_SG_H
131*4882a593Smuzhiyun #define LINUX_CB710_SG_H
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun #include <linux/highmem.h>
134*4882a593Smuzhiyun #include <linux/scatterlist.h>
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun * 32-bit PIO mapping sg iterator
138*4882a593Smuzhiyun *
139*4882a593Smuzhiyun * Hides scatterlist access issues - fragment boundaries, alignment, page
140*4882a593Smuzhiyun * mapping - for drivers using 32-bit-word-at-a-time-PIO (ie. PCI devices
141*4882a593Smuzhiyun * without DMA support).
142*4882a593Smuzhiyun *
143*4882a593Smuzhiyun * Best-case reading (transfer from device):
144*4882a593Smuzhiyun * sg_miter_start(, SG_MITER_TO_SG);
145*4882a593Smuzhiyun * cb710_sg_dwiter_write_from_io();
146*4882a593Smuzhiyun * sg_miter_stop();
147*4882a593Smuzhiyun *
148*4882a593Smuzhiyun * Best-case writing (transfer to device):
149*4882a593Smuzhiyun * sg_miter_start(, SG_MITER_FROM_SG);
150*4882a593Smuzhiyun * cb710_sg_dwiter_read_to_io();
151*4882a593Smuzhiyun * sg_miter_stop();
152*4882a593Smuzhiyun */
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun uint32_t cb710_sg_dwiter_read_next_block(struct sg_mapping_iter *miter);
155*4882a593Smuzhiyun void cb710_sg_dwiter_write_next_block(struct sg_mapping_iter *miter, uint32_t data);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /**
158*4882a593Smuzhiyun * cb710_sg_dwiter_write_from_io - transfer data to mapped buffer from 32-bit IO port
159*4882a593Smuzhiyun * @miter: sg mapping iter
160*4882a593Smuzhiyun * @port: PIO port - IO or MMIO address
161*4882a593Smuzhiyun * @count: number of 32-bit words to transfer
162*4882a593Smuzhiyun *
163*4882a593Smuzhiyun * Description:
164*4882a593Smuzhiyun * Reads @count 32-bit words from register @port and stores it in
165*4882a593Smuzhiyun * buffer iterated by @miter. Data that would overflow the buffer
166*4882a593Smuzhiyun * is silently ignored. Iterator is advanced by 4*@count bytes
167*4882a593Smuzhiyun * or to the buffer's end whichever is closer.
168*4882a593Smuzhiyun *
169*4882a593Smuzhiyun * Context:
170*4882a593Smuzhiyun * IRQ disabled if the SG_MITER_ATOMIC is set. Don't care otherwise.
171*4882a593Smuzhiyun */
cb710_sg_dwiter_write_from_io(struct sg_mapping_iter * miter,void __iomem * port,size_t count)172*4882a593Smuzhiyun static inline void cb710_sg_dwiter_write_from_io(struct sg_mapping_iter *miter,
173*4882a593Smuzhiyun void __iomem *port, size_t count)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun while (count-- > 0)
176*4882a593Smuzhiyun cb710_sg_dwiter_write_next_block(miter, ioread32(port));
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /**
180*4882a593Smuzhiyun * cb710_sg_dwiter_read_to_io - transfer data to 32-bit IO port from mapped buffer
181*4882a593Smuzhiyun * @miter: sg mapping iter
182*4882a593Smuzhiyun * @port: PIO port - IO or MMIO address
183*4882a593Smuzhiyun * @count: number of 32-bit words to transfer
184*4882a593Smuzhiyun *
185*4882a593Smuzhiyun * Description:
186*4882a593Smuzhiyun * Writes @count 32-bit words to register @port from buffer iterated
187*4882a593Smuzhiyun * through @miter. If buffer ends before @count words are written
188*4882a593Smuzhiyun * missing data is replaced by zeroes. @miter is advanced by 4*@count
189*4882a593Smuzhiyun * bytes or to the buffer's end whichever is closer.
190*4882a593Smuzhiyun *
191*4882a593Smuzhiyun * Context:
192*4882a593Smuzhiyun * IRQ disabled if the SG_MITER_ATOMIC is set. Don't care otherwise.
193*4882a593Smuzhiyun */
cb710_sg_dwiter_read_to_io(struct sg_mapping_iter * miter,void __iomem * port,size_t count)194*4882a593Smuzhiyun static inline void cb710_sg_dwiter_read_to_io(struct sg_mapping_iter *miter,
195*4882a593Smuzhiyun void __iomem *port, size_t count)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun while (count-- > 0)
198*4882a593Smuzhiyun iowrite32(cb710_sg_dwiter_read_next_block(miter), port);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun #endif /* LINUX_CB710_SG_H */
202