forked from Minki/linux
spi: meson-spicc: enhance output enable feature
The SPICC controller in Meson-AXG is capable of driving the CLK/MOSI/SS signal lines through the idle state (between two transmission operation), which avoid the signals floating in unexpected state. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Yixun Lan <yixun.lan@amlogic.com> Signed-off-by: Sunny Luo <sunny.luo@amlogic.com> Link: https://lore.kernel.org/r/20200312133131.26430-3-narmstrong@baylibre.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
b9dfb20eed
commit
a6cda1f905
@ -9,11 +9,13 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/types.h>
|
||||
@ -113,12 +115,23 @@
|
||||
|
||||
#define SPICC_DWADDR 0x24 /* Write Address of DMA */
|
||||
|
||||
#define SPICC_ENH_CTL0 0x38 /* Enhanced Feature */
|
||||
#define SPICC_ENH_MOSI_OEN BIT(25)
|
||||
#define SPICC_ENH_CLK_OEN BIT(26)
|
||||
#define SPICC_ENH_CS_OEN BIT(27)
|
||||
#define SPICC_ENH_CLK_CS_DELAY_EN BIT(28)
|
||||
#define SPICC_ENH_MAIN_CLK_AO BIT(29)
|
||||
|
||||
#define writel_bits_relaxed(mask, val, addr) \
|
||||
writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr)
|
||||
|
||||
#define SPICC_BURST_MAX 16
|
||||
#define SPICC_FIFO_HALF 10
|
||||
|
||||
struct meson_spicc_data {
|
||||
bool has_oen;
|
||||
};
|
||||
|
||||
struct meson_spicc_device {
|
||||
struct spi_master *master;
|
||||
struct platform_device *pdev;
|
||||
@ -126,6 +139,7 @@ struct meson_spicc_device {
|
||||
struct clk *core;
|
||||
struct spi_message *message;
|
||||
struct spi_transfer *xfer;
|
||||
const struct meson_spicc_data *data;
|
||||
u8 *tx_buf;
|
||||
u8 *rx_buf;
|
||||
unsigned int bytes_per_word;
|
||||
@ -136,6 +150,19 @@ struct meson_spicc_device {
|
||||
bool is_last_burst;
|
||||
};
|
||||
|
||||
static void meson_spicc_oen_enable(struct meson_spicc_device *spicc)
|
||||
{
|
||||
u32 conf;
|
||||
|
||||
if (!spicc->data->has_oen)
|
||||
return;
|
||||
|
||||
conf = readl_relaxed(spicc->base + SPICC_ENH_CTL0) |
|
||||
SPICC_ENH_MOSI_OEN | SPICC_ENH_CLK_OEN | SPICC_ENH_CS_OEN;
|
||||
|
||||
writel_relaxed(conf, spicc->base + SPICC_ENH_CTL0);
|
||||
}
|
||||
|
||||
static inline bool meson_spicc_txfull(struct meson_spicc_device *spicc)
|
||||
{
|
||||
return !!FIELD_GET(SPICC_TF,
|
||||
@ -489,6 +516,13 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
||||
spicc = spi_master_get_devdata(master);
|
||||
spicc->master = master;
|
||||
|
||||
spicc->data = of_device_get_match_data(&pdev->dev);
|
||||
if (!spicc->data) {
|
||||
dev_err(&pdev->dev, "failed to get match data\n");
|
||||
ret = -EINVAL;
|
||||
goto out_master;
|
||||
}
|
||||
|
||||
spicc->pdev = pdev;
|
||||
platform_set_drvdata(pdev, spicc);
|
||||
|
||||
@ -548,6 +582,8 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
||||
else
|
||||
master->max_speed_hz = rate >> 2;
|
||||
|
||||
meson_spicc_oen_enable(spicc);
|
||||
|
||||
ret = devm_spi_register_master(&pdev->dev, master);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "spi master registration failed\n");
|
||||
@ -577,9 +613,22 @@ static int meson_spicc_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct meson_spicc_data meson_spicc_gx_data = {
|
||||
};
|
||||
|
||||
static const struct meson_spicc_data meson_spicc_axg_data = {
|
||||
.has_oen = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id meson_spicc_of_match[] = {
|
||||
{ .compatible = "amlogic,meson-gx-spicc", },
|
||||
{ .compatible = "amlogic,meson-axg-spicc", },
|
||||
{
|
||||
.compatible = "amlogic,meson-gx-spicc",
|
||||
.data = &meson_spicc_gx_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson-axg-spicc",
|
||||
.data = &meson_spicc_axg_data,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, meson_spicc_of_match);
|
||||
|
Loading…
Reference in New Issue
Block a user