Skip to content

Commit db4fa45

Browse files
Anders Bergbroonie
authored andcommitted
spi: pl022: Add support for chip select extension
Add support for a extended PL022 which has an extra register for controlling up to five chip select signals. This controller is found on the AXM5516 SoC. Unfortunately the PrimeCell identification registers are identical to a standard ARM PL022. To work around this, the peripheral ID must be overridden in the device tree using the "arm,primecell-periphid" property with the value 0x000b6022. Signed-off-by: Anders Berg <[email protected]> Acked-by: Linus Walleij <[email protected]> Acked-by: Russell King <[email protected]> Signed-off-by: Mark Brown <[email protected]>
1 parent 73e3f1e commit db4fa45

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

drivers/spi/spi-pl022.c

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
#define SSP_MIS(r) (r + 0x01C)
8383
#define SSP_ICR(r) (r + 0x020)
8484
#define SSP_DMACR(r) (r + 0x024)
85+
#define SSP_CSR(r) (r + 0x030) /* vendor extension */
8586
#define SSP_ITCR(r) (r + 0x080)
8687
#define SSP_ITIP(r) (r + 0x084)
8788
#define SSP_ITOP(r) (r + 0x088)
@@ -197,6 +198,12 @@
197198
/* Transmit DMA Enable bit */
198199
#define SSP_DMACR_MASK_TXDMAE (0x1UL << 1)
199200

201+
/*
202+
* SSP Chip Select Control Register - SSP_CSR
203+
* (vendor extension)
204+
*/
205+
#define SSP_CSR_CSVALUE_MASK (0x1FUL << 0)
206+
200207
/*
201208
* SSP Integration Test control Register - SSP_ITCR
202209
*/
@@ -313,6 +320,7 @@ enum ssp_writing {
313320
* @extended_cr: 32 bit wide control register 0 with extra
314321
* features and extra features in CR1 as found in the ST variants
315322
* @pl023: supports a subset of the ST extensions called "PL023"
323+
* @internal_cs_ctrl: supports chip select control register
316324
*/
317325
struct vendor_data {
318326
int fifodepth;
@@ -321,6 +329,7 @@ struct vendor_data {
321329
bool extended_cr;
322330
bool pl023;
323331
bool loopback;
332+
bool internal_cs_ctrl;
324333
};
325334

326335
/**
@@ -440,9 +449,32 @@ static void null_cs_control(u32 command)
440449
pr_debug("pl022: dummy chip select control, CS=0x%x\n", command);
441450
}
442451

452+
/**
453+
* internal_cs_control - Control chip select signals via SSP_CSR.
454+
* @pl022: SSP driver private data structure
455+
* @command: select/delect the chip
456+
*
457+
* Used on controller with internal chip select control via SSP_CSR register
458+
* (vendor extension). Each of the 5 LSB in the register controls one chip
459+
* select signal.
460+
*/
461+
static void internal_cs_control(struct pl022 *pl022, u32 command)
462+
{
463+
u32 tmp;
464+
465+
tmp = readw(SSP_CSR(pl022->virtbase));
466+
if (command == SSP_CHIP_SELECT)
467+
tmp &= ~BIT(pl022->cur_cs);
468+
else
469+
tmp |= BIT(pl022->cur_cs);
470+
writew(tmp, SSP_CSR(pl022->virtbase));
471+
}
472+
443473
static void pl022_cs_control(struct pl022 *pl022, u32 command)
444474
{
445-
if (gpio_is_valid(pl022->cur_cs))
475+
if (pl022->vendor->internal_cs_ctrl)
476+
internal_cs_control(pl022, command);
477+
else if (gpio_is_valid(pl022->cur_cs))
446478
gpio_set_value(pl022->cur_cs, command);
447479
else
448480
pl022->cur_chip->cs_control(command);
@@ -2122,6 +2154,9 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
21222154
if (platform_info->num_chipselect && platform_info->chipselects) {
21232155
for (i = 0; i < num_cs; i++)
21242156
pl022->chipselects[i] = platform_info->chipselects[i];
2157+
} else if (pl022->vendor->internal_cs_ctrl) {
2158+
for (i = 0; i < num_cs; i++)
2159+
pl022->chipselects[i] = i;
21252160
} else if (IS_ENABLED(CONFIG_OF)) {
21262161
for (i = 0; i < num_cs; i++) {
21272162
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
@@ -2352,6 +2387,7 @@ static struct vendor_data vendor_arm = {
23522387
.extended_cr = false,
23532388
.pl023 = false,
23542389
.loopback = true,
2390+
.internal_cs_ctrl = false,
23552391
};
23562392

23572393
static struct vendor_data vendor_st = {
@@ -2361,6 +2397,7 @@ static struct vendor_data vendor_st = {
23612397
.extended_cr = true,
23622398
.pl023 = false,
23632399
.loopback = true,
2400+
.internal_cs_ctrl = false,
23642401
};
23652402

23662403
static struct vendor_data vendor_st_pl023 = {
@@ -2370,6 +2407,17 @@ static struct vendor_data vendor_st_pl023 = {
23702407
.extended_cr = true,
23712408
.pl023 = true,
23722409
.loopback = false,
2410+
.internal_cs_ctrl = false,
2411+
};
2412+
2413+
static struct vendor_data vendor_lsi = {
2414+
.fifodepth = 8,
2415+
.max_bpw = 16,
2416+
.unidir = false,
2417+
.extended_cr = false,
2418+
.pl023 = false,
2419+
.loopback = true,
2420+
.internal_cs_ctrl = true,
23732421
};
23742422

23752423
static struct amba_id pl022_ids[] = {
@@ -2403,6 +2451,15 @@ static struct amba_id pl022_ids[] = {
24032451
.mask = 0xffffffff,
24042452
.data = &vendor_st_pl023,
24052453
},
2454+
{
2455+
/*
2456+
* PL022 variant that has a chip select control register whih
2457+
* allows control of 5 output signals nCS[0:4].
2458+
*/
2459+
.id = 0x000b6022,
2460+
.mask = 0x000fffff,
2461+
.data = &vendor_lsi,
2462+
},
24062463
{ 0, 0 },
24072464
};
24082465

include/linux/amba/bus.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,15 @@ struct amba_driver {
4444
const struct amba_id *id_table;
4545
};
4646

47+
/*
48+
* Constants for the designer field of the Peripheral ID register. When bit 7
49+
* is set to '1', bits [6:0] should be the JEP106 manufacturer identity code.
50+
*/
4751
enum amba_vendor {
4852
AMBA_VENDOR_ARM = 0x41,
4953
AMBA_VENDOR_ST = 0x80,
5054
AMBA_VENDOR_QCOM = 0x51,
55+
AMBA_VENDOR_LSI = 0xb6,
5156
};
5257

5358
extern struct bus_type amba_bustype;

0 commit comments

Comments
 (0)