You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'spi/next' of git://git.secretlab.ca/git/linux-2.6
* 'spi/next' of git://git.secretlab.ca/git/linux-2.6: drivercore: Add helper macro for platform_driver boilerplate spi: irq: Remove IRQF_DISABLED OMAP: SPI: Fix the trying to free nonexistent resource error spi/spi-ep93xx: add module.h include spi/tegra: fix compilation error in spi-tegra.c spi: spi-dw: fix all sparse warnings spi/spi-pl022: Call pl022_dma_remove(pl022) only if enable_dma is true spi/spi-pl022: calculate_effective_freq() must set rate <= requested rate spi/spi-pl022: Don't allocate more sg than required. spi/spi-pl022: Use GFP_ATOMIC for allocation from tasklet spi/spi-pl022: Resolve formatting issues
This commit is contained in:
+67
-77
@@ -113,7 +113,6 @@
|
||||
#define SSP_CR0_MASK_CSS_ST (0x1FUL << 16)
|
||||
#define SSP_CR0_MASK_FRF_ST (0x3UL << 21)
|
||||
|
||||
|
||||
/*
|
||||
* SSP Control Register 0 - SSP_CR1
|
||||
*/
|
||||
@@ -283,7 +282,6 @@
|
||||
|
||||
#define SPI_POLLING_TIMEOUT 1000
|
||||
|
||||
|
||||
/*
|
||||
* The type of reading going on on this chip
|
||||
*/
|
||||
@@ -749,7 +747,6 @@ static void readwriter(struct pl022 *pl022)
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* next_transfer - Move to the Next transfer in the current spi message
|
||||
* @pl022: SSP driver private data structure
|
||||
@@ -1016,14 +1013,14 @@ static int configure_dma(struct pl022 *pl022)
|
||||
dmaengine_slave_config(txchan, &tx_conf);
|
||||
|
||||
/* Create sglists for the transfers */
|
||||
pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1;
|
||||
pages = DIV_ROUND_UP(pl022->cur_transfer->len, PAGE_SIZE);
|
||||
dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
|
||||
|
||||
ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_KERNEL);
|
||||
ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_ATOMIC);
|
||||
if (ret)
|
||||
goto err_alloc_rx_sg;
|
||||
|
||||
ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_KERNEL);
|
||||
ret = sg_alloc_table(&pl022->sgt_tx, pages, GFP_ATOMIC);
|
||||
if (ret)
|
||||
goto err_alloc_tx_sg;
|
||||
|
||||
@@ -1531,8 +1528,7 @@ static void pump_messages(struct work_struct *work)
|
||||
/* Initial message state */
|
||||
pl022->cur_msg->state = STATE_START;
|
||||
pl022->cur_transfer = list_entry(pl022->cur_msg->transfers.next,
|
||||
struct spi_transfer,
|
||||
transfer_list);
|
||||
struct spi_transfer, transfer_list);
|
||||
|
||||
/* Setup the SPI using the per chip configuration */
|
||||
pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
|
||||
@@ -1551,7 +1547,6 @@ static void pump_messages(struct work_struct *work)
|
||||
do_interrupt_dma_transfer(pl022);
|
||||
}
|
||||
|
||||
|
||||
static int __init init_queue(struct pl022 *pl022)
|
||||
{
|
||||
INIT_LIST_HEAD(&pl022->queue);
|
||||
@@ -1560,8 +1555,8 @@ static int __init init_queue(struct pl022 *pl022)
|
||||
pl022->running = false;
|
||||
pl022->busy = false;
|
||||
|
||||
tasklet_init(&pl022->pump_transfers,
|
||||
pump_transfers, (unsigned long)pl022);
|
||||
tasklet_init(&pl022->pump_transfers, pump_transfers,
|
||||
(unsigned long)pl022);
|
||||
|
||||
INIT_WORK(&pl022->pump_messages, pump_messages);
|
||||
pl022->workqueue = create_singlethread_workqueue(
|
||||
@@ -1572,7 +1567,6 @@ static int __init init_queue(struct pl022 *pl022)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int start_queue(struct pl022 *pl022)
|
||||
{
|
||||
unsigned long flags;
|
||||
@@ -1595,7 +1589,6 @@ static int start_queue(struct pl022 *pl022)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int stop_queue(struct pl022 *pl022)
|
||||
{
|
||||
unsigned long flags;
|
||||
@@ -1791,71 +1784,70 @@ static int pl022_transfer(struct spi_device *spi, struct spi_message *msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int calculate_effective_freq(struct pl022 *pl022,
|
||||
int freq,
|
||||
struct ssp_clock_params *clk_freq)
|
||||
static inline u32 spi_rate(u32 rate, u16 cpsdvsr, u16 scr)
|
||||
{
|
||||
return rate / (cpsdvsr * (1 + scr));
|
||||
}
|
||||
|
||||
static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
|
||||
ssp_clock_params * clk_freq)
|
||||
{
|
||||
/* Lets calculate the frequency parameters */
|
||||
u16 cpsdvsr = 2;
|
||||
u16 scr = 0;
|
||||
bool freq_found = false;
|
||||
u32 rate;
|
||||
u32 max_tclk;
|
||||
u32 min_tclk;
|
||||
u16 cpsdvsr = CPSDVR_MIN, scr = SCR_MIN;
|
||||
u32 rate, max_tclk, min_tclk, best_freq = 0, best_cpsdvsr = 0,
|
||||
best_scr = 0, tmp, found = 0;
|
||||
|
||||
rate = clk_get_rate(pl022->clk);
|
||||
/* cpsdvscr = 2 & scr 0 */
|
||||
max_tclk = (rate / (CPSDVR_MIN * (1 + SCR_MIN)));
|
||||
max_tclk = spi_rate(rate, CPSDVR_MIN, SCR_MIN);
|
||||
/* cpsdvsr = 254 & scr = 255 */
|
||||
min_tclk = (rate / (CPSDVR_MAX * (1 + SCR_MAX)));
|
||||
min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
|
||||
|
||||
if ((freq <= max_tclk) && (freq >= min_tclk)) {
|
||||
while (cpsdvsr <= CPSDVR_MAX && !freq_found) {
|
||||
while (scr <= SCR_MAX && !freq_found) {
|
||||
if ((rate /
|
||||
(cpsdvsr * (1 + scr))) > freq)
|
||||
scr += 1;
|
||||
else {
|
||||
/*
|
||||
* This bool is made true when
|
||||
* effective frequency >=
|
||||
* target frequency is found
|
||||
*/
|
||||
freq_found = true;
|
||||
if ((rate /
|
||||
(cpsdvsr * (1 + scr))) != freq) {
|
||||
if (scr == SCR_MIN) {
|
||||
cpsdvsr -= 2;
|
||||
scr = SCR_MAX;
|
||||
} else
|
||||
scr -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!freq_found) {
|
||||
cpsdvsr += 2;
|
||||
scr = SCR_MIN;
|
||||
}
|
||||
}
|
||||
if (cpsdvsr != 0) {
|
||||
dev_dbg(&pl022->adev->dev,
|
||||
"SSP Effective Frequency is %u\n",
|
||||
(rate / (cpsdvsr * (1 + scr))));
|
||||
clk_freq->cpsdvsr = (u8) (cpsdvsr & 0xFF);
|
||||
clk_freq->scr = (u8) (scr & 0xFF);
|
||||
dev_dbg(&pl022->adev->dev,
|
||||
"SSP cpsdvsr = %d, scr = %d\n",
|
||||
clk_freq->cpsdvsr, clk_freq->scr);
|
||||
}
|
||||
} else {
|
||||
if (!((freq <= max_tclk) && (freq >= min_tclk))) {
|
||||
dev_err(&pl022->adev->dev,
|
||||
"controller data is incorrect: out of range frequency");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* best_freq will give closest possible available rate (<= requested
|
||||
* freq) for all values of scr & cpsdvsr.
|
||||
*/
|
||||
while ((cpsdvsr <= CPSDVR_MAX) && !found) {
|
||||
while (scr <= SCR_MAX) {
|
||||
tmp = spi_rate(rate, cpsdvsr, scr);
|
||||
|
||||
if (tmp > freq)
|
||||
scr++;
|
||||
/*
|
||||
* If found exact value, update and break.
|
||||
* If found more closer value, update and continue.
|
||||
*/
|
||||
else if ((tmp == freq) || (tmp > best_freq)) {
|
||||
best_freq = tmp;
|
||||
best_cpsdvsr = cpsdvsr;
|
||||
best_scr = scr;
|
||||
|
||||
if (tmp == freq)
|
||||
break;
|
||||
}
|
||||
scr++;
|
||||
}
|
||||
cpsdvsr += 2;
|
||||
scr = SCR_MIN;
|
||||
}
|
||||
|
||||
clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
|
||||
clk_freq->scr = (u8) (best_scr & 0xFF);
|
||||
dev_dbg(&pl022->adev->dev,
|
||||
"SSP Target Frequency is: %u, Effective Frequency is %u\n",
|
||||
freq, best_freq);
|
||||
dev_dbg(&pl022->adev->dev, "SSP cpsdvsr = %d, scr = %d\n",
|
||||
clk_freq->cpsdvsr, clk_freq->scr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A piece of default chip info unless the platform
|
||||
* supplies it.
|
||||
@@ -1873,7 +1865,6 @@ static const struct pl022_config_chip pl022_default_chip_info = {
|
||||
.cs_control = null_cs_control,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* pl022_setup - setup function registered to SPI master framework
|
||||
* @spi: spi device which is requesting setup
|
||||
@@ -1950,7 +1941,6 @@ static int pl022_setup(struct spi_device *spi)
|
||||
goto err_config_params;
|
||||
}
|
||||
|
||||
|
||||
status = verify_controller_parameters(pl022, chip_info);
|
||||
if (status) {
|
||||
dev_err(&spi->dev, "controller data is incorrect");
|
||||
@@ -2090,7 +2080,8 @@ static int pl022_setup(struct spi_device *spi)
|
||||
}
|
||||
SSP_WRITE_BITS(chip->cr1, SSP_DISABLED, SSP_CR1_MASK_SSE, 1);
|
||||
SSP_WRITE_BITS(chip->cr1, chip_info->hierarchy, SSP_CR1_MASK_MS, 2);
|
||||
SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD, 3);
|
||||
SSP_WRITE_BITS(chip->cr1, chip_info->slave_tx_disable, SSP_CR1_MASK_SOD,
|
||||
3);
|
||||
|
||||
/* Save controller_state */
|
||||
spi_set_ctldata(spi, chip);
|
||||
@@ -2116,7 +2107,6 @@ static void pl022_cleanup(struct spi_device *spi)
|
||||
kfree(chip);
|
||||
}
|
||||
|
||||
|
||||
static int __devinit
|
||||
pl022_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
@@ -2242,7 +2232,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
err_start_queue:
|
||||
err_init_queue:
|
||||
destroy_queue(pl022);
|
||||
pl022_dma_remove(pl022);
|
||||
if (platform_info->enable_dma)
|
||||
pl022_dma_remove(pl022);
|
||||
|
||||
free_irq(adev->irq[0], pl022);
|
||||
err_no_irq:
|
||||
clk_unprepare(pl022->clk);
|
||||
@@ -2277,7 +2269,9 @@ pl022_remove(struct amba_device *adev)
|
||||
if (destroy_queue(pl022) != 0)
|
||||
dev_err(&adev->dev, "queue remove failed\n");
|
||||
load_ssp_default_config(pl022);
|
||||
pl022_dma_remove(pl022);
|
||||
if (pl022->master_info->enable_dma)
|
||||
pl022_dma_remove(pl022);
|
||||
|
||||
free_irq(adev->irq[0], pl022);
|
||||
clk_disable(pl022->clk);
|
||||
clk_unprepare(pl022->clk);
|
||||
@@ -2364,7 +2358,6 @@ static struct vendor_data vendor_arm = {
|
||||
.loopback = true,
|
||||
};
|
||||
|
||||
|
||||
static struct vendor_data vendor_st = {
|
||||
.fifodepth = 32,
|
||||
.max_bpw = 32,
|
||||
@@ -2419,9 +2412,9 @@ static struct amba_id pl022_ids[] = {
|
||||
* and 32 locations deep TX/RX FIFO but no extended
|
||||
* CR0/CR1 register
|
||||
*/
|
||||
.id = 0x00080023,
|
||||
.mask = 0xffffffff,
|
||||
.data = &vendor_st_pl023,
|
||||
.id = 0x00080023,
|
||||
.mask = 0xffffffff,
|
||||
.data = &vendor_st_pl023,
|
||||
},
|
||||
{
|
||||
.id = 0x10080023,
|
||||
@@ -2441,19 +2434,16 @@ static struct amba_driver pl022_driver = {
|
||||
.remove = __devexit_p(pl022_remove),
|
||||
};
|
||||
|
||||
|
||||
static int __init pl022_init(void)
|
||||
{
|
||||
return amba_driver_register(&pl022_driver);
|
||||
}
|
||||
|
||||
subsys_initcall(pl022_init);
|
||||
|
||||
static void __exit pl022_exit(void)
|
||||
{
|
||||
amba_driver_unregister(&pl022_driver);
|
||||
}
|
||||
|
||||
module_exit(pl022_exit);
|
||||
|
||||
MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
|
||||
|
||||
Reference in New Issue
Block a user