This series adds support for DVB Frontend system named HSC support
for UniPhier LD11/LD20 SoCs. This driver supports MPEG2-TS serial
signal input from external demodulator and DMA MPEG2-TS stream data
onto memory.
UniPhier HSC driver provides many ports of TS input. Since the HSC
has mixed register map for those ports. It hard to split each register
areas.
---
Changes from v1:
DT bindings
- Fix mistakes of spelling
- Rename uniphier,hsc.txt -> socionext,uniphier-hsc.txt
Kconfig, Makefile
- Add COMPILE_TEST, REGMAP_MMIO
- Add $(srctree) to include path option
Headers
- Split large patch
- Remove more unused definitions
- Remove unneeded const
- Replace enum that has special value into #define
- Remove weird macro from register definitions
- Remove field_get/prop inline functions
Modules
- Split register definitions, function prototypes
- Fix include lines
- Fix depended config
- Remove redundant conditions
- Drop adapter patches, and need no patches to build
- Merge uniphier-adapter.o into each adapter drivers
- Split 3 modules (core, ld11, ld20) to build adapter drivers as
module
- Fix compile error if build as module
- Use hardware spec table to remove weird macro from register
definitions
- Use usleep_range instead of msleep
- Use shift and mask instead of field_get/prop inline functions
Katsuhiro Suzuki (7):
media: uniphier: add DT bindings documentation for UniPhier HSC
media: uniphier: add DMA common file of HSC
media: uniphier: add CSS common file of HSC
media: uniphier: add TS common file of HSC
media: uniphier: add ucode load common file of HSC
media: uniphier: add platform driver module of HSC
media: uniphier: add LD11/LD20 HSC support
.../bindings/media/socionext,uniphier-hsc.txt | 38 ++
drivers/media/platform/Kconfig | 1 +
drivers/media/platform/Makefile | 2 +
drivers/media/platform/uniphier/Kconfig | 19 +
drivers/media/platform/uniphier/Makefile | 5 +
drivers/media/platform/uniphier/hsc-core.c | 515 ++++++++++++++++++
drivers/media/platform/uniphier/hsc-css.c | 250 +++++++++
drivers/media/platform/uniphier/hsc-dma.c | 212 +++++++
drivers/media/platform/uniphier/hsc-ld11.c | 273 ++++++++++
drivers/media/platform/uniphier/hsc-reg.h | 272 +++++++++
drivers/media/platform/uniphier/hsc-ts.c | 127 +++++
drivers/media/platform/uniphier/hsc-ucode.c | 416 ++++++++++++++
drivers/media/platform/uniphier/hsc.h | 389 +++++++++++++
13 files changed, 2519 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/socionext,uniphier-hsc.txt
create mode 100644 drivers/media/platform/uniphier/Kconfig
create mode 100644 drivers/media/platform/uniphier/Makefile
create mode 100644 drivers/media/platform/uniphier/hsc-core.c
create mode 100644 drivers/media/platform/uniphier/hsc-css.c
create mode 100644 drivers/media/platform/uniphier/hsc-dma.c
create mode 100644 drivers/media/platform/uniphier/hsc-ld11.c
create mode 100644 drivers/media/platform/uniphier/hsc-reg.h
create mode 100644 drivers/media/platform/uniphier/hsc-ts.c
create mode 100644 drivers/media/platform/uniphier/hsc-ucode.c
create mode 100644 drivers/media/platform/uniphier/hsc.h
--
2.18.0
Add TS input/output code to start/stop configure the MPEG2-TS ports
of HSC for Socionext UniPhier SoCs.
Signed-off-by: Katsuhiro Suzuki <[email protected]>
---
Changes from v1:
- Split from large patches
- Fix include lines
---
drivers/media/platform/uniphier/Makefile | 2 +-
drivers/media/platform/uniphier/hsc-reg.h | 41 +++++++
drivers/media/platform/uniphier/hsc-ts.c | 127 ++++++++++++++++++++++
drivers/media/platform/uniphier/hsc.h | 6 +
4 files changed, 175 insertions(+), 1 deletion(-)
create mode 100644 drivers/media/platform/uniphier/hsc-ts.c
diff --git a/drivers/media/platform/uniphier/Makefile b/drivers/media/platform/uniphier/Makefile
index 59be2edf0c53..2ba03067644d 100644
--- a/drivers/media/platform/uniphier/Makefile
+++ b/drivers/media/platform/uniphier/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-uniphier-dvb-y += hsc-dma.o hsc-css.o
+uniphier-dvb-y += hsc-dma.o hsc-css.o hsc-ts.o
obj-$(CONFIG_DVB_UNIPHIER) += uniphier-dvb.o
diff --git a/drivers/media/platform/uniphier/hsc-reg.h b/drivers/media/platform/uniphier/hsc-reg.h
index e5bc87658361..26f04b79178b 100644
--- a/drivers/media/platform/uniphier/hsc-reg.h
+++ b/drivers/media/platform/uniphier/hsc-reg.h
@@ -144,4 +144,45 @@
#define CSS_DPCTRL_DPSEL_TSI1 BIT(1)
#define CSS_DPCTRL_DPSEL_TSI0 BIT(0)
+/* TSI */
+#define TSI_SYNCCNTROL(i) (0x7100 + (i) * 0x70)
+#define TSI_SYNCCNTROL_FRAME_MASK GENMASK(18, 16)
+#define TSI_SYNCCNTROL_FRAME_EXTSYNC1 (0x0 << 16)
+#define TSI_SYNCCNTROL_FRAME_EXTSYNC2 (0x1 << 16)
+#define TSI_CONFIG(i) (0x7104 + (i) * 0x70)
+#define TSI_CONFIG_ATSMD_MASK GENMASK(22, 21)
+#define TSI_CONFIG_ATSMD_PCRPLL0 (0x0 << 21)
+#define TSI_CONFIG_ATSMD_PCRPLL1 (0x1 << 21)
+#define TSI_CONFIG_ATSMD_DPLL (0x3 << 21)
+#define TSI_CONFIG_ATSADD_ON BIT(20)
+#define TSI_CONFIG_STCMD_MASK GENMASK(7, 6)
+#define TSI_CONFIG_STCMD_PCRPLL0 (0x0 << 6)
+#define TSI_CONFIG_STCMD_PCRPLL1 (0x1 << 6)
+#define TSI_CONFIG_STCMD_DPLL (0x3 << 6)
+#define TSI_CONFIG_CHEN_START BIT(0)
+#define TSI_RATEUPLMT(i) (0x7108 + (i) * 0x70)
+#define TSI_RATELOWLMT(i) (0x710c + (i) * 0x70)
+#define TSI_CNTINTR(i) (0x7110 + (i) * 0x70)
+#define TSI_INTREN(i) (0x7114 + (i) * 0x70)
+#define TSI_INTR_NTP BIT(13)
+#define TSI_INTR_NTPCNT BIT(12)
+#define TSI_INTR_PKTEND BIT(11)
+#define TSI_INTR_PCR BIT(9)
+#define TSI_INTR_LOAD BIT(8)
+#define TSI_INTR_SERR BIT(7)
+#define TSI_INTR_SOF BIT(6)
+#define TSI_INTR_TOF BIT(5)
+#define TSI_INTR_UL BIT(4)
+#define TSI_INTR_LL BIT(3)
+#define TSI_INTR_CNT BIT(2)
+#define TSI_INTR_LOST BIT(1)
+#define TSI_INTR_LOCK BIT(0)
+#define TSI_SYNCSTATUS(i) (0x7118 + (i) * 0x70)
+#define TSI_STAT_PKTST_ERR BIT(21)
+#define TSI_STAT_LARGE_ERR BIT(20)
+#define TSI_STAT_SMALL_ERR BIT(19)
+#define TSI_STAT_LOCK BIT(18)
+#define TSI_STAT_SYNC BIT(17)
+#define TSI_STAT_SEARCH BIT(16)
+
#endif /* DVB_UNIPHIER_HSC_REG_H__ */
diff --git a/drivers/media/platform/uniphier/hsc-ts.c b/drivers/media/platform/uniphier/hsc-ts.c
new file mode 100644
index 000000000000..bb70429301ad
--- /dev/null
+++ b/drivers/media/platform/uniphier/hsc-ts.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext UniPhier DVB driver for High-speed Stream Controller (HSC).
+// MPEG2-TS input/output port setting.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/bitfield.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+
+#include "hsc.h"
+#include "hsc-reg.h"
+
+/* SBC1, 2 */
+#define SBC_ACE_DMA_EN 0x6000
+#define SBC_DMAPARAM21 0x6004
+#define SBC_ACE_INTREN 0x6008
+#define SBC_ACE_INTRST 0x600c
+#define SBC_DMA_STATUS0 0x6010
+#define SBC_DMA_STATUS1 0x6014
+#define SBC_DMAPARAMA(i) (0x6018 + (i) * 0x04)
+#define SBC_DMAPARAMA_OFFSET_MASK GENMASK(31, 29)
+#define SBC_DMAPARAMA_LOOPADDR_MASK GENMASK(28, 23)
+#define SBC_DMAPARAMA_COUNT_MASK GENMASK(7, 0)
+#define SBC_DMAPARAMB(i) (0x6038 + (i) * 0x04)
+
+#define PARAMA_OFFSET_TS 0x02
+#define PARAMA_LOOPADDR_TS 0x31
+#define PARAMA_COUNT_TS 0xc4
+
+static bool ts_in_is_valid(struct hsc_chip *chip, int tsi)
+{
+ return tsi < chip->spec->num_ts_in && chip->spec->ts_in[tsi].intr.valid;
+}
+
+static const struct hsc_spec_ts *ts_in_get_spec(struct hsc_chip *chip, int tsi)
+{
+ const struct hsc_spec_ts *spec = chip->spec->ts_in;
+
+ if (!ts_in_is_valid(chip, tsi))
+ return NULL;
+
+ return &spec[tsi];
+}
+
+int hsc_ts_in_set_enable(struct hsc_chip *chip, int tsi, bool en)
+{
+ struct regmap *r = chip->regmap;
+ const struct hsc_spec_ts *speci = ts_in_get_spec(chip, tsi);
+ u32 m, v;
+
+ if (!speci)
+ return -EINVAL;
+
+ m = TSI_SYNCCNTROL_FRAME_MASK;
+ v = TSI_SYNCCNTROL_FRAME_EXTSYNC2;
+ regmap_update_bits(r, TSI_SYNCCNTROL(tsi), m, v);
+
+ m = TSI_CONFIG_ATSMD_MASK | TSI_CONFIG_STCMD_MASK |
+ TSI_CONFIG_CHEN_START;
+ v = TSI_CONFIG_ATSMD_DPLL | TSI_CONFIG_STCMD_DPLL;
+ if (en)
+ v |= TSI_CONFIG_CHEN_START;
+ regmap_update_bits(r, TSI_CONFIG(tsi), m, v);
+
+ v = (en) ? ~0 : 0;
+ regmap_update_bits(r, TSI_INTREN(tsi),
+ TSI_INTR_SERR | TSI_INTR_LOST, v);
+ regmap_update_bits(r, speci->intr.reg, BIT(speci->intr.sft), v);
+
+ return 0;
+}
+
+int hsc_ts_in_set_dmaparam(struct hsc_chip *chip, int tsi, int ifmt)
+{
+ struct regmap *r = chip->regmap;
+ u32 v, ats, offset, loop, cnt;
+
+ if (!ts_in_is_valid(chip, tsi))
+ return -EINVAL;
+
+ switch (ifmt) {
+ case HSC_TSIF_MPEG2_TS:
+ ats = 0;
+ offset = PARAMA_OFFSET_TS;
+ loop = PARAMA_LOOPADDR_TS;
+ cnt = PARAMA_COUNT_TS;
+ break;
+ case HSC_TSIF_MPEG2_TS_ATS:
+ ats = TSI_CONFIG_ATSADD_ON;
+ offset = PARAMA_OFFSET_TS;
+ loop = PARAMA_LOOPADDR_TS;
+ cnt = PARAMA_COUNT_TS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_update_bits(r, TSI_CONFIG(tsi), TSI_CONFIG_ATSADD_ON, ats);
+
+ v = FIELD_PREP(SBC_DMAPARAMA_OFFSET_MASK, offset) |
+ FIELD_PREP(SBC_DMAPARAMA_LOOPADDR_MASK, loop) |
+ FIELD_PREP(SBC_DMAPARAMA_COUNT_MASK, cnt);
+ regmap_write(r, SBC_DMAPARAMA(tsi), v);
+
+ return 0;
+}
+
+int hsc_ts_in_get_intr(struct hsc_chip *chip, int tsi, u32 *stat)
+{
+ struct regmap *r = chip->regmap;
+
+ if (!stat)
+ return -EINVAL;
+
+ regmap_read(r, TSI_SYNCSTATUS(tsi), stat);
+
+ return 0;
+}
+
+void hsc_ts_in_clear_intr(struct hsc_chip *chip, int tsi, u32 clear)
+{
+ struct regmap *r = chip->regmap;
+
+ regmap_write(r, TSI_SYNCSTATUS(tsi), clear);
+}
diff --git a/drivers/media/platform/uniphier/hsc.h b/drivers/media/platform/uniphier/hsc.h
index 1cbd17b475bf..a10b7a480193 100644
--- a/drivers/media/platform/uniphier/hsc.h
+++ b/drivers/media/platform/uniphier/hsc.h
@@ -346,6 +346,12 @@ int hsc_css_out_set_polarity(struct hsc_chip *chip, int out,
int hsc_css_out_get_src(struct hsc_chip *chip, int *in, int out, bool *en);
int hsc_css_out_set_src(struct hsc_chip *chip, int in, int out, bool en);
+/* TS */
+int hsc_ts_in_set_enable(struct hsc_chip *chip, int tsi, bool en);
+int hsc_ts_in_set_dmaparam(struct hsc_chip *chip, int tsi, int ifmt);
+int hsc_ts_in_get_intr(struct hsc_chip *chip, int tsi, u32 *st);
+void hsc_ts_in_clear_intr(struct hsc_chip *chip, int tsi, u32 clear);
+
/* DMA */
u64 hsc_rb_cnt(struct hsc_dma_buf *buf);
u64 hsc_rb_cnt_to_end(struct hsc_dma_buf *buf);
--
2.18.0
This patch adds definition of registers specs to support of HSC
MPEG2-TS I/O driver for UniPhier LD11/LD20 SoCs.
Signed-off-by: Katsuhiro Suzuki <[email protected]>
---
drivers/media/platform/uniphier/Kconfig | 8 +
drivers/media/platform/uniphier/Makefile | 1 +
drivers/media/platform/uniphier/hsc-ld11.c | 273 +++++++++++++++++++++
3 files changed, 282 insertions(+)
create mode 100644 drivers/media/platform/uniphier/hsc-ld11.c
diff --git a/drivers/media/platform/uniphier/Kconfig b/drivers/media/platform/uniphier/Kconfig
index b96b98d98400..5a08d09b76ff 100644
--- a/drivers/media/platform/uniphier/Kconfig
+++ b/drivers/media/platform/uniphier/Kconfig
@@ -9,3 +9,11 @@ config DVB_UNIPHIER
Driver for UniPhier frontend for MPEG2-TS input/output,
demux and descramble.
Say Y when you want to support this frontend.
+
+config DVB_UNIPHIER_LD11
+ bool "Support UniPhier LD11/LD20 HSC Device Driver"
+ depends on DVB_UNIPHIER
+ help
+ Driver for the HSC (High speed Stream Controller) for
+ UniPhier LD11/LD20.
+ Say Y when you want to support this hardware.
diff --git a/drivers/media/platform/uniphier/Makefile b/drivers/media/platform/uniphier/Makefile
index d17e001a7195..165a44b649c9 100644
--- a/drivers/media/platform/uniphier/Makefile
+++ b/drivers/media/platform/uniphier/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
uniphier-dvb-y += hsc-dma.o hsc-css.o hsc-ts.o hsc-ucode.o hsc-core.o
+uniphier-dvb-$(CONFIG_DVB_UNIPHIER_LD11) += hsc-ld11.o
obj-$(CONFIG_DVB_UNIPHIER) += uniphier-dvb.o
diff --git a/drivers/media/platform/uniphier/hsc-ld11.c b/drivers/media/platform/uniphier/hsc-ld11.c
new file mode 100644
index 000000000000..3d33bf12b8d7
--- /dev/null
+++ b/drivers/media/platform/uniphier/hsc-ld11.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext UniPhier DVB driver for High-speed Stream Controller (HSC).
+// For UniPhier LD11/LD20.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include "hsc.h"
+#include "hsc-reg.h"
+
+static const struct hsc_spec_init_ram uniphier_hsc_ld11_init_rams[] = {
+ { FLT_PATN_RAM_TOP_ADDR, FLT_PATN_RAM_SIZE, ~0, },
+ { FLT_MASK_RAM_TOP_ADDR, FLT_MASK_RAM_SIZE, 0, },
+ /* FLT_PID Pattern */
+ { SHARE_MEMORY_0_NORMAL, FLT_PIDPATTERN_SIZE, ~0, },
+ /* FLT_PID Table */
+ { SHARE_MEMORY_0_NORMAL + FLT_PIDPATTERN_SIZE,
+ SHARE_MEMORY_0_SIZE - FLT_PIDPATTERN_SIZE, 0, },
+ { SHARE_MEMORY_1_NORMAL, SHARE_MEMORY_1_SIZE, 0, },
+ { SHARE_MEMORY_2_NORMAL, SHARE_MEMORY_2_SIZE, 0, },
+ { SHARE_MEMORY_3_NORMAL, SHARE_MEMORY_3_SIZE, 0, },
+ { SHARE_MEMORY_4_NORMAL, SHARE_MEMORY_4_SIZE, 0, },
+ { SHARE_MEMORY_5_NORMAL, SHARE_MEMORY_5_SIZE, 0, },
+};
+
+static const struct hsc_spec_init_ram uniphier_hsc_ld20_init_rams[] = {
+ { FLT_PATN_RAM_TOP_ADDR, FLT_PATN_RAM_SIZE, ~0, },
+ { FLT_MASK_RAM_TOP_ADDR, FLT_MASK_RAM_SIZE, 0, },
+ /* FLT_PID Pattern */
+ { SHARE_MEMORY_0_NORMAL, FLT_PIDPATTERN_SIZE, ~0, },
+ /* FLT_PID Table */
+ { SHARE_MEMORY_0_NORMAL + FLT_PIDPATTERN_SIZE,
+ SHARE_MEMORY_0_SIZE - FLT_PIDPATTERN_SIZE, 0, },
+ { SHARE_MEMORY_1_NORMAL, SHARE_MEMORY_1_SIZE, 0, },
+ { SHARE_MEMORY_2_NORMAL, SHARE_MEMORY_2_SIZE, 0, },
+ { SHARE_MEMORY_3_NORMAL, SHARE_MEMORY_3_SIZE, 0, },
+ { SHARE_MEMORY_4_NORMAL, SHARE_MEMORY_4_SIZE, 0, },
+ { SHARE_MEMORY_5_NORMAL, SHARE_MEMORY_5_SIZE, 0, },
+ { SHARE_MEMORY_6_NORMAL, SHARE_MEMORY_6_SIZE, 0, },
+ { SHARE_MEMORY_7_NORMAL, SHARE_MEMORY_7_SIZE, 0, },
+};
+
+static const struct hsc_spec_css uniphier_hsc_ld11_css_in[] = {
+ [HSC_CSS_IN_SRLTS0] = {
+ .pol = { true, CSS_SIGNALPOLCH(0), -1, 3, 0, },
+ },
+ [HSC_CSS_IN_SRLTS1] = {
+ .pol = { true, CSS_SIGNALPOLCH(0), -1, 11, 8, },
+ },
+ [HSC_CSS_IN_SRLTS2] = {
+ .pol = { true, CSS_SIGNALPOLCH(0), -1, 19, 16, },
+ },
+ [HSC_CSS_IN_SRLTS3] = {
+ .pol = { true, CSS_SIGNALPOLCH(0), -1, 27, 24, },
+ },
+ [HSC_CSS_IN_SRLTS4] = {
+ .pol = { true, CSS_SIGNALPOLCH(1), -1, 3, 0, },
+ },
+ [HSC_CSS_IN_PARTS0] = {
+ .pol = { true, CSS_PTSISIGNALPOL, -1, -1, 0, },
+ },
+ [HSC_CSS_IN_PARTS1] = {
+ .pol = { true, CSS_PTSISIGNALPOL, -1, -1, 8, },
+ },
+ [HSC_CSS_IN_DMD0] = {
+ .pol = { true, CSS_DMDSIGNALPOL, -1, -1, 16, },
+ },
+};
+
+static const struct hsc_spec_css uniphier_hsc_ld11_css_out[] = {
+ [HSC_CSS_OUT_SRLTS0] = {
+ .pol = { true, CSS_STSOSIGNALPOL, 6, -1, 0, },
+ .sel = { true, CSS_OUTPUTCTRL(0), GENMASK(4, 0), 0, },
+ },
+ [HSC_CSS_OUT_SRLTS1] = {
+ .pol = { true, CSS_STSOSIGNALPOL, 14, -1, 8, },
+ .sel = { true, CSS_OUTPUTCTRL(0), GENMASK(12, 8), 8, },
+ },
+ [HSC_CSS_OUT_TSI0] = {
+ .sel = { true, CSS_OUTPUTCTRL(1), GENMASK(4, 0), 0, },
+ },
+ [HSC_CSS_OUT_TSI1] = {
+ .sel = { true, CSS_OUTPUTCTRL(1), GENMASK(12, 8), 8, },
+ },
+ [HSC_CSS_OUT_TSI2] = {
+ .sel = { true, CSS_OUTPUTCTRL(1), GENMASK(20, 16), 16, },
+ },
+ [HSC_CSS_OUT_TSI3] = {
+ .sel = { true, CSS_OUTPUTCTRL(1), GENMASK(28, 24), 24, },
+ },
+ [HSC_CSS_OUT_TSI4] = {
+ .sel = { true, CSS_OUTPUTCTRL(2), GENMASK(4, 0), 0, },
+ },
+ [HSC_CSS_OUT_PARTS0] = {
+ .pol = { true, CSS_PTSOSIGNALPOL, -1, -1, 0, },
+ .sel = { true, CSS_OUTPUTCTRL(4), GENMASK(4, 0), 0, },
+ },
+ [HSC_CSS_OUT_PKTFF0] = {
+ .sel = { true, CSS_OUTPUTCTRL(5), GENMASK(4, 0), 0, },
+ },
+};
+
+static const struct hsc_spec_ts uniphier_hsc_ld11_ts_in[] = {
+ [HSC_TS_IN0] = {
+ .intr = { true, IOB_INTREN0, 13 },
+ },
+ [HSC_TS_IN1] = {
+ .intr = { true, IOB_INTREN0, 14 },
+ },
+ [HSC_TS_IN2] = {
+ .intr = { true, IOB_INTREN0, 15 },
+ },
+ [HSC_TS_IN3] = {
+ .intr = { true, IOB_INTREN0, 16 },
+ },
+ [HSC_TS_IN4] = {
+ .intr = { true, IOB_INTREN0, 17 },
+ },
+};
+
+static const struct hsc_spec_dma uniphier_hsc_ld11_dma_in[] = {
+ [HSC_DMA_IN0] = {
+ .dma_ch = 5,
+ .rb_ch = 4,
+ .it_ch = 0,
+ .en = { true, CDMBC_TDSTRT, 5 },
+ .intr = { true, IOB_INTREN1, 1 },
+ },
+ [HSC_DMA_IN1] = {
+ .dma_ch = 6,
+ .rb_ch = 5,
+ .it_ch = 1,
+ .en = { true, CDMBC_TDSTRT, 6 },
+ .intr = { true, IOB_INTREN1, 2 },
+ },
+ [HSC_DMA_IN2] = {
+ .dma_ch = 7,
+ .rb_ch = 6,
+ .it_ch = 2,
+ .en = { true, CDMBC_TDSTRT, 7 },
+ .intr = { true, IOB_INTREN1, 3 },
+ },
+ [HSC_DMA_IN3] = {
+ .dma_ch = 22,
+ .rb_ch = 20,
+ .it_ch = 13,
+ .en = { true, CDMBC_TDSTRT, 13 },
+ .intr = { true, IOB_INTREN1, 4 },
+ },
+ [HSC_DMA_IN4] = {
+ .dma_ch = 23,
+ .rb_ch = 21,
+ .it_ch = 14,
+ .en = { true, CDMBC_TDSTRT, 14 },
+ .intr = { true, IOB_INTREN1, 5 },
+ },
+ [HSC_DMA_IN5] = {
+ .dma_ch = 24,
+ .rb_ch = 22,
+ .it_ch = 15,
+ .en = { true, CDMBC_TDSTRT, 15 },
+ .intr = { true, IOB_INTREN1, 6 },
+ },
+ [HSC_DMA_CIP_IN0] = {
+ .dma_ch = 8,
+ .rb_ch = 7,
+ .cip_ch = 0,
+ .it_ch = 3,
+ .en = { true, CDMBC_STRT(1), 0 },
+ .intr = { true, IOB_INTREN2, 4 },
+ },
+ [HSC_DMA_CIP_IN1] = {
+ .dma_ch = 10,
+ .rb_ch = 9,
+ .cip_ch = 1,
+ .it_ch = 5,
+ .en = { true, CDMBC_STRT(1), 2 },
+ .intr = { true, IOB_INTREN2, 5 },
+ },
+};
+
+static const struct hsc_spec_dma uniphier_hsc_ld11_dma_out[] = {
+ [HSC_DMA_OUT0] = {
+ .dma_ch = 1,
+ .rb_ch = 1,
+ .td_ch = 0,
+ .en = { true, CDMBC_TDSTRT, 1 },
+ .intr = { true, IOB_INTREN1, 13 },
+ },
+ [HSC_DMA_OUT1] = {
+ .dma_ch = 2,
+ .rb_ch = 2,
+ .td_ch = 2,
+ .en = { true, CDMBC_TDSTRT, 2 },
+ .intr = { true, IOB_INTREN1, 14 },
+ },
+ [HSC_DMA_OUT2] = {
+ .dma_ch = 3,
+ .rb_ch = 3,
+ .td_ch = 4,
+ .en = { true, CDMBC_TDSTRT, 3 },
+ .intr = { true, IOB_INTREN1, 15 },
+ },
+ [HSC_DMA_OUT3] = {
+ .dma_ch = 19,
+ .rb_ch = 17,
+ .td_ch = 1,
+ .en = { true, CDMBC_TDSTRT, 9 },
+ .intr = { true, IOB_INTREN1, 16 },
+ },
+ [HSC_DMA_OUT4] = {
+ .dma_ch = 20,
+ .rb_ch = 18,
+ .td_ch = 3,
+ .en = { true, CDMBC_TDSTRT, 10 },
+ .intr = { true, IOB_INTREN1, 17 },
+ },
+ [HSC_DMA_OUT5] = {
+ .dma_ch = 21,
+ .rb_ch = 19,
+ .td_ch = 5,
+ .en = { true, CDMBC_TDSTRT, 11 },
+ .intr = { true, IOB_INTREN1, 18 },
+ },
+ [HSC_DMA_CIP_OUT0] = {
+ .dma_ch = 9,
+ .rb_ch = 8,
+ .cip_ch = 0,
+ .en = { true, CDMBC_STRT(1), 1 },
+ .intr = { true, IOB_INTREN2, 9 },
+ },
+ [HSC_DMA_CIP_OUT1] = {
+ .dma_ch = 11,
+ .rb_ch = 10,
+ .cip_ch = 1,
+ .en = { true, CDMBC_STRT(1), 3 },
+ .intr = { true, IOB_INTREN2, 10 },
+ },
+};
+
+const struct hsc_spec uniphier_hsc_ld11_spec = {
+ .ucode_spu = { "hsc_spu_code_ld11.bin", "hsc_spu_data_ld11.bin" },
+ .ucode_ace = { "hsc_ace_code_ld11.bin", "hsc_ace_data_ld11.bin" },
+ .init_rams = uniphier_hsc_ld11_init_rams,
+ .num_init_rams = ARRAY_SIZE(uniphier_hsc_ld11_init_rams),
+ .css_in = uniphier_hsc_ld11_css_in,
+ .num_css_in = ARRAY_SIZE(uniphier_hsc_ld11_css_in),
+ .css_out = uniphier_hsc_ld11_css_out,
+ .num_css_out = ARRAY_SIZE(uniphier_hsc_ld11_css_out),
+ .ts_in = uniphier_hsc_ld11_ts_in,
+ .num_ts_in = ARRAY_SIZE(uniphier_hsc_ld11_ts_in),
+ .dma_in = uniphier_hsc_ld11_dma_in,
+ .num_dma_in = ARRAY_SIZE(uniphier_hsc_ld11_dma_in),
+ .dma_out = uniphier_hsc_ld11_dma_out,
+ .num_dma_out = ARRAY_SIZE(uniphier_hsc_ld11_dma_out),
+};
+
+const struct hsc_spec uniphier_hsc_ld20_spec = {
+ .ucode_spu = { "hsc_spu_code_ld11.bin", "hsc_spu_data_ld11.bin" },
+ .ucode_ace = { "hsc_ace_code_ld11.bin", "hsc_ace_data_ld11.bin" },
+ .init_rams = uniphier_hsc_ld20_init_rams,
+ .num_init_rams = ARRAY_SIZE(uniphier_hsc_ld20_init_rams),
+ .css_in = uniphier_hsc_ld11_css_in,
+ .num_css_in = ARRAY_SIZE(uniphier_hsc_ld11_css_in),
+ .css_out = uniphier_hsc_ld11_css_out,
+ .num_css_out = ARRAY_SIZE(uniphier_hsc_ld11_css_out),
+ .ts_in = uniphier_hsc_ld11_ts_in,
+ .num_ts_in = ARRAY_SIZE(uniphier_hsc_ld11_ts_in),
+ .dma_in = uniphier_hsc_ld11_dma_in,
+ .num_dma_in = ARRAY_SIZE(uniphier_hsc_ld11_dma_in),
+ .dma_out = uniphier_hsc_ld11_dma_out,
+ .num_dma_out = ARRAY_SIZE(uniphier_hsc_ld11_dma_out),
+};
--
2.18.0
This patch adds common platform driver module of HSC (High speed
Stream Controller) driver for Socionext UniPhier SoCs.
Signed-off-by: Katsuhiro Suzuki <[email protected]>
---
Changes from v1:
- Add DMA mask
- Fix compile error if build as module
- Add missing MODULE_AUTHOR, DESCRIPTION and LICENSE
- Replace enum that has special value into #define
- Use hardware spec table to remove weird macro from register
definitions
- Fix include lines
---
drivers/media/platform/uniphier/Makefile | 2 +-
drivers/media/platform/uniphier/hsc-core.c | 515 +++++++++++++++++++++
drivers/media/platform/uniphier/hsc-reg.h | 25 +
drivers/media/platform/uniphier/hsc.h | 10 +
4 files changed, 551 insertions(+), 1 deletion(-)
create mode 100644 drivers/media/platform/uniphier/hsc-core.c
diff --git a/drivers/media/platform/uniphier/Makefile b/drivers/media/platform/uniphier/Makefile
index 79b4dc44df94..d17e001a7195 100644
--- a/drivers/media/platform/uniphier/Makefile
+++ b/drivers/media/platform/uniphier/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-uniphier-dvb-y += hsc-dma.o hsc-css.o hsc-ts.o hsc-ucode.o
+uniphier-dvb-y += hsc-dma.o hsc-css.o hsc-ts.o hsc-ucode.o hsc-core.o
obj-$(CONFIG_DVB_UNIPHIER) += uniphier-dvb.o
diff --git a/drivers/media/platform/uniphier/hsc-core.c b/drivers/media/platform/uniphier/hsc-core.c
new file mode 100644
index 000000000000..464568e90297
--- /dev/null
+++ b/drivers/media/platform/uniphier/hsc-core.c
@@ -0,0 +1,515 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext UniPhier DVB driver for High-speed Stream Controller (HSC).
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "hsc.h"
+#include "hsc-reg.h"
+
+#define SZ_TS_PKT 188
+#define SZ_M2TS_PKT 192
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nums);
+
+static int hsc_start_feed(struct dvb_demux_feed *feed)
+{
+ struct hsc_tsif *tsif = feed->demux->priv;
+ struct hsc_dmaif *dmaif = tsif->dmaif;
+ struct hsc_chip *chip = tsif->chip;
+
+ tsif->running = true;
+ dmaif->running = true;
+
+ hsc_ts_in_set_enable(chip, tsif->tsi, true);
+
+ hsc_dma_out_set_src_ts_in(&dmaif->dma_out, tsif->tsi);
+ hsc_dma_out_start(&dmaif->dma_out, true);
+
+ return 0;
+}
+
+static int hsc_stop_feed(struct dvb_demux_feed *feed)
+{
+ struct hsc_tsif *tsif = feed->demux->priv;
+ struct hsc_dmaif *dmaif = tsif->dmaif;
+ struct hsc_chip *chip = tsif->chip;
+
+ hsc_ts_in_set_enable(chip, tsif->tsi, false);
+
+ hsc_dma_out_start(&dmaif->dma_out, false);
+
+ tsif->running = false;
+ dmaif->running = false;
+
+ return 0;
+}
+
+int hsc_register_dvb(struct hsc_tsif *tsif)
+{
+ struct device *dev = &tsif->chip->pdev->dev;
+ int ret;
+
+ tsif->adapter.priv = tsif;
+ ret = dvb_register_adapter(&tsif->adapter, "uniphier-hsc",
+ THIS_MODULE, dev, adapter_nums);
+ if (ret < 0) {
+ dev_err(dev, "Failed to register DVB adapter: %d\n", ret);
+ return ret;
+ }
+ tsif->valid_adapter = true;
+
+ tsif->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+ tsif->demux.priv = tsif;
+ tsif->demux.feednum = 256;
+ tsif->demux.filternum = 256;
+ tsif->demux.start_feed = hsc_start_feed;
+ tsif->demux.stop_feed = hsc_stop_feed;
+ tsif->demux.write_to_decoder = NULL;
+ ret = dvb_dmx_init(&tsif->demux);
+ if (ret) {
+ dev_err(dev, "Failed to register demux: %d\n", ret);
+ goto err_out_adapter;
+ }
+ tsif->valid_demux = true;
+
+ tsif->dmxdev.filternum = 256;
+ tsif->dmxdev.demux = &tsif->demux.dmx;
+ tsif->dmxdev.capabilities = 0;
+ ret = dvb_dmxdev_init(&tsif->dmxdev, &tsif->adapter);
+ if (ret) {
+ dev_err(dev, "Failed to register demux dev: %d\n", ret);
+ goto err_out_dmx;
+ }
+ tsif->valid_dmxdev = true;
+
+ ret = dvb_register_frontend(&tsif->adapter, tsif->fe);
+ if (ret) {
+ dev_err(dev, "Failed to register adapter: %d\n", ret);
+ goto err_out_dmxdev;
+ }
+ tsif->valid_fe = true;
+
+ return 0;
+
+err_out_dmxdev:
+ dvb_dmxdev_release(&tsif->dmxdev);
+
+err_out_dmx:
+ dvb_dmx_release(&tsif->demux);
+
+err_out_adapter:
+ dvb_unregister_adapter(&tsif->adapter);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hsc_register_dvb);
+
+void hsc_unregister_dvb(struct hsc_tsif *tsif)
+{
+ if (tsif->valid_fe)
+ dvb_unregister_frontend(tsif->fe);
+ if (tsif->valid_dmxdev)
+ dvb_dmxdev_release(&tsif->dmxdev);
+ if (tsif->valid_demux)
+ dvb_dmx_release(&tsif->demux);
+ if (tsif->valid_adapter)
+ dvb_unregister_adapter(&tsif->adapter);
+}
+EXPORT_SYMBOL_GPL(hsc_unregister_dvb);
+
+static bool is_tsi_error(struct hsc_tsif *tsif, u32 status)
+{
+ if (status & (TSI_INTR_SERR | TSI_INTR_SOF | TSI_INTR_TOF))
+ return true;
+
+ return false;
+}
+
+static void hsc_tsif_recover_worker(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct hsc_tsif *tsif = container_of(dwork,
+ struct hsc_tsif, recover_work);
+ struct hsc_chip *chip = tsif->chip;
+
+ if (!tsif->running)
+ return;
+
+ hsc_ts_in_set_enable(chip, tsif->tsi, true);
+}
+
+static irqreturn_t hsc_tsif_irq(int irq, void *p)
+{
+ struct platform_device *pdev = p;
+ struct hsc_chip *chip = platform_get_drvdata(pdev);
+ irqreturn_t result = IRQ_NONE;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(chip->tsif); i++) {
+ struct hsc_tsif *tsif = &chip->tsif[i];
+ u32 st;
+
+ if (!tsif->running)
+ continue;
+
+ ret = hsc_ts_in_get_intr(chip, tsif->tsi, &st);
+ if (ret || !st)
+ continue;
+
+ hsc_ts_in_clear_intr(chip, tsif->tsi, 0xffff);
+
+ if (is_tsi_error(tsif, st))
+ schedule_delayed_work(&tsif->recover_work,
+ tsif->recover_delay);
+
+ result = IRQ_HANDLED;
+ }
+
+ return result;
+}
+
+int hsc_tsif_init(struct hsc_tsif *tsif, const struct hsc_conf *conf)
+{
+ struct hsc_chip *chip = tsif->chip;
+ int ret;
+
+ if (!conf)
+ return -EINVAL;
+
+ tsif->css_in = conf->css_in;
+ tsif->css_out = conf->css_out;
+ tsif->dpll = conf->dpll;
+
+ tsif->tsi = hsc_css_out_to_ts_in(tsif->css_out);
+ if (tsif->tsi == -1)
+ return -EINVAL;
+
+ tsif->dpll_src = hsc_css_out_to_dpll_src(tsif->css_out);
+ if (tsif->dpll_src == -1)
+ return -EINVAL;
+
+ ret = hsc_css_out_set_src(chip, tsif->css_in, tsif->css_out, true);
+ if (ret)
+ return ret;
+
+ ret = hsc_css_in_set_polarity(chip, tsif->css_in, false, false, false);
+ if (ret)
+ return ret;
+
+ ret = hsc_ts_in_set_dmaparam(chip, tsif->tsi, HSC_TSIF_MPEG2_TS_ATS);
+ if (ret)
+ return ret;
+
+ ret = hsc_dpll_set_src(chip, tsif->dpll, tsif->dpll_src);
+ if (ret)
+ return ret;
+
+ INIT_DELAYED_WORK(&tsif->recover_work, hsc_tsif_recover_worker);
+ tsif->recover_delay = HZ / 10;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hsc_tsif_init);
+
+void hsc_tsif_release(struct hsc_tsif *tsif)
+{
+ cancel_delayed_work(&tsif->recover_work);
+}
+EXPORT_SYMBOL_GPL(hsc_tsif_release);
+
+static void hsc_dmaif_feed_worker(struct work_struct *work)
+{
+ struct hsc_dmaif *dmaif = container_of(work,
+ struct hsc_dmaif, feed_work);
+ struct hsc_tsif *tsif = dmaif->tsif;
+ struct hsc_dma_buf *buf = &dmaif->buf_out;
+ struct device *dev = &dmaif->chip->pdev->dev;
+ dma_addr_t dmapos;
+ u8 *pkt;
+ u64 cnt, i;
+ int wrap = 0;
+
+ if (!dmaif->running)
+ return;
+
+retry:
+ spin_lock(&dmaif->lock);
+ hsc_dma_out_sync(&dmaif->dma_out);
+ spin_unlock(&dmaif->lock);
+
+ dmapos = buf->phys + buf->rd_offs;
+ cnt = hsc_rb_cnt_to_end(buf);
+ cnt = DIV_ROUND_DOWN_ULL(cnt, SZ_M2TS_PKT) * SZ_M2TS_PKT;
+
+ dma_sync_single_for_cpu(dev, dmapos, cnt, DMA_FROM_DEVICE);
+ for (i = 0; i < cnt; i += SZ_M2TS_PKT) {
+ pkt = buf->virt + buf->rd_offs + i;
+ dvb_dmx_swfilter_packets(&tsif->demux, &pkt[4], 1);
+ }
+ dma_sync_single_for_device(dev, dmapos, cnt, DMA_FROM_DEVICE);
+
+ spin_lock(&dmaif->lock);
+
+ buf->rd_offs += cnt;
+ if (buf->rd_offs >= buf->size)
+ buf->rd_offs -= buf->size;
+
+ buf->chk_offs = buf->wr_offs + buf->size_chk;
+ if (buf->chk_offs >= buf->size)
+ buf->chk_offs -= buf->size;
+
+ if (!wrap && hsc_rb_cnt(buf) >= buf->size_chk / 2) {
+ wrap = 1;
+ spin_unlock(&dmaif->lock);
+ goto retry;
+ }
+
+ hsc_dma_out_sync(&dmaif->dma_out);
+
+ spin_unlock(&dmaif->lock);
+}
+
+static irqreturn_t hsc_dmaif_irq(int irq, void *p)
+{
+ struct platform_device *pdev = p;
+ struct hsc_chip *chip = platform_get_drvdata(pdev);
+ irqreturn_t result = IRQ_NONE;
+ int i, ret;
+ u32 st;
+
+ for (i = 0; i < ARRAY_SIZE(chip->tsif); i++) {
+ struct hsc_dmaif *dmaif = &chip->dmaif[i];
+
+ if (!dmaif->running)
+ continue;
+
+ ret = hsc_dma_out_get_intr(&dmaif->dma_out, &st);
+ if (ret || !st)
+ continue;
+
+ hsc_dma_out_clear_intr(&dmaif->dma_out, 0xffff);
+
+ spin_lock(&dmaif->lock);
+ hsc_dma_out_sync(&dmaif->dma_out);
+ spin_unlock(&dmaif->lock);
+
+ schedule_work(&dmaif->feed_work);
+
+ result = IRQ_HANDLED;
+ }
+
+ return result;
+}
+
+int hsc_dmaif_init(struct hsc_dmaif *dmaif, const struct hsc_conf *conf)
+{
+ struct hsc_chip *chip = dmaif->chip;
+ struct hsc_dma_buf *buf = &dmaif->buf_out;
+ struct device *dev = &chip->pdev->dev;
+ int ret;
+
+ if (!conf)
+ return -EINVAL;
+
+ ret = hsc_dma_out_init(&dmaif->dma_out, chip, conf->dma_out, buf);
+ if (ret)
+ return ret;
+
+ buf->size = HSC_DMAIF_TS_BUFSIZE;
+ buf->size_chk = HSC_DMAIF_TS_BUFSIZE / 4;
+ buf->virt = dma_alloc_coherent(dev, buf->size, &buf->phys, GFP_KERNEL);
+ if (!buf->virt)
+ return -ENOMEM;
+
+ spin_lock_init(&dmaif->lock);
+ INIT_WORK(&dmaif->feed_work, hsc_dmaif_feed_worker);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hsc_dmaif_init);
+
+void hsc_dmaif_release(struct hsc_dmaif *dmaif)
+{
+ struct hsc_chip *chip = dmaif->chip;
+ struct device *dev = &chip->pdev->dev;
+
+ flush_scheduled_work();
+
+ dma_free_coherent(dev, dmaif->buf_out.size, dmaif->buf_out.virt,
+ dmaif->buf_out.phys);
+}
+EXPORT_SYMBOL_GPL(hsc_dmaif_release);
+
+static const struct regmap_config hsc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0xffffc,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int hsc_probe(struct platform_device *pdev)
+{
+ struct hsc_chip *chip;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ void __iomem *preg;
+ int irq, ret, i;
+
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+ chip->pdev = pdev;
+
+ chip->spec = of_device_get_match_data(dev);
+ if (!chip->spec)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ preg = devm_ioremap_resource(dev, res);
+ if (IS_ERR(preg))
+ return PTR_ERR(preg);
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33));
+ if (ret)
+ return ret;
+
+ chip->regmap = devm_regmap_init_mmio(dev, preg,
+ &hsc_regmap_config);
+ if (IS_ERR(chip->regmap))
+ return PTR_ERR(chip->regmap);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "Could not get irq for TS I/F\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, hsc_tsif_irq, IRQF_SHARED,
+ dev_name(dev), pdev);
+ if (ret)
+ return ret;
+
+ irq = platform_get_irq(pdev, 1);
+ if (irq < 0) {
+ dev_err(dev, "Could not get irq for DMA I/F\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(dev, irq, hsc_dmaif_irq, IRQF_SHARED,
+ dev_name(dev), pdev);
+ if (ret)
+ return ret;
+
+ chip->clk_stdmac = devm_clk_get(dev, "stdmac");
+ if (IS_ERR(chip->clk_stdmac))
+ return PTR_ERR(chip->clk_stdmac);
+
+ chip->clk_hsc = devm_clk_get(dev, "hsc");
+ if (IS_ERR(chip->clk_hsc))
+ return PTR_ERR(chip->clk_hsc);
+
+ chip->rst_stdmac = devm_reset_control_get_shared(dev, "stdmac");
+ if (IS_ERR(chip->rst_stdmac))
+ return PTR_ERR(chip->rst_stdmac);
+
+ chip->rst_hsc = devm_reset_control_get_shared(dev, "hsc");
+ if (IS_ERR(chip->rst_hsc))
+ return PTR_ERR(chip->rst_hsc);
+
+ ret = clk_prepare_enable(chip->clk_stdmac);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(chip->clk_hsc);
+ if (ret)
+ goto err_out_clk_stdmac;
+
+ ret = reset_control_deassert(chip->rst_stdmac);
+ if (ret)
+ goto err_out_clk_hsc;
+
+ ret = reset_control_deassert(chip->rst_hsc);
+ if (ret)
+ goto err_out_rst_stdmac;
+
+ ret = hsc_ucode_load_all(chip);
+ if (ret)
+ goto err_out_rst_hsc;
+
+ for (i = 0; i < HSC_STREAM_IF_NUM; i++) {
+ chip->dmaif[i].chip = chip;
+ chip->dmaif[i].tsif = &chip->tsif[i];
+ chip->tsif[i].chip = chip;
+ chip->tsif[i].dmaif = &chip->dmaif[i];
+ }
+
+ platform_set_drvdata(pdev, chip);
+
+ return 0;
+
+err_out_rst_hsc:
+ reset_control_assert(chip->rst_hsc);
+
+err_out_rst_stdmac:
+ reset_control_assert(chip->rst_stdmac);
+
+err_out_clk_hsc:
+ clk_disable_unprepare(chip->clk_hsc);
+
+err_out_clk_stdmac:
+ clk_disable_unprepare(chip->clk_stdmac);
+
+ return ret;
+}
+
+static int hsc_remove(struct platform_device *pdev)
+{
+ struct hsc_chip *chip = platform_get_drvdata(pdev);
+
+ hsc_ucode_unload_all(chip);
+
+ reset_control_assert(chip->rst_hsc);
+ reset_control_assert(chip->rst_stdmac);
+ clk_disable_unprepare(chip->clk_hsc);
+ clk_disable_unprepare(chip->clk_stdmac);
+
+ return 0;
+}
+
+static const struct of_device_id uniphier_hsc_of_match[] = {
+ {
+ .compatible = "socionext,uniphier-ld11-hsc",
+ .data = &uniphier_hsc_ld11_spec,
+ },
+ {
+ .compatible = "socionext,uniphier-ld20-hsc",
+ .data = &uniphier_hsc_ld20_spec,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, uniphier_hsc_of_match);
+
+static struct platform_driver uniphier_hsc_driver = {
+ .driver = {
+ .name = "uniphier-hsc",
+ .of_match_table = of_match_ptr(uniphier_hsc_of_match),
+ },
+ .probe = hsc_probe,
+ .remove = hsc_remove,
+};
+module_platform_driver(uniphier_hsc_driver);
+
+MODULE_AUTHOR("Katsuhiro Suzuki <[email protected]>");
+MODULE_DESCRIPTION("UniPhier DVB driver for HSC.");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/uniphier/hsc-reg.h b/drivers/media/platform/uniphier/hsc-reg.h
index 1ca3ad55330f..69aa37caefce 100644
--- a/drivers/media/platform/uniphier/hsc-reg.h
+++ b/drivers/media/platform/uniphier/hsc-reg.h
@@ -8,6 +8,31 @@
#ifndef DVB_UNIPHIER_HSC_REG_H__
#define DVB_UNIPHIER_HSC_REG_H__
+/* RAM Address */
+#define FLT_PATN_RAM_TOP_ADDR 0x0a000
+#define FLT_MASK_RAM_TOP_ADDR 0x0b000
+#define SHARE_MEMORY_0_NORMAL 0x10000
+#define SHARE_MEMORY_1_NORMAL 0x11000
+#define SHARE_MEMORY_2_NORMAL 0x12000
+#define SHARE_MEMORY_3_NORMAL 0x13000
+#define SHARE_MEMORY_4_NORMAL 0x14000
+#define SHARE_MEMORY_5_NORMAL 0x15000
+#define SHARE_MEMORY_6_NORMAL 0x16000
+#define SHARE_MEMORY_7_NORMAL 0x17000
+
+/* RAM size */
+#define FLT_PATN_RAM_SIZE 0x0800
+#define FLT_MASK_RAM_SIZE 0x0800
+#define FLT_PIDPATTERN_SIZE 0x0160
+#define SHARE_MEMORY_0_SIZE 0x1000
+#define SHARE_MEMORY_1_SIZE 0x1000
+#define SHARE_MEMORY_2_SIZE 0x1000
+#define SHARE_MEMORY_3_SIZE 0x1000
+#define SHARE_MEMORY_4_SIZE 0x1000
+#define SHARE_MEMORY_5_SIZE 0x1000
+#define SHARE_MEMORY_6_SIZE 0x1000
+#define SHARE_MEMORY_7_SIZE 0x1000
+
/* IOB1, 2, 3 */
#define IOB_PKTCNT 0x1740
#define IOB_PKTCNTRST 0x1744
diff --git a/drivers/media/platform/uniphier/hsc.h b/drivers/media/platform/uniphier/hsc.h
index bbfd90ffaad5..e60c80ac55e6 100644
--- a/drivers/media/platform/uniphier/hsc.h
+++ b/drivers/media/platform/uniphier/hsc.h
@@ -376,4 +376,14 @@ void hsc_dma_out_clear_intr(struct hsc_dma *dma_out, u32 clear);
int hsc_ucode_load_all(struct hsc_chip *chip);
int hsc_ucode_unload_all(struct hsc_chip *chip);
+/* For Adapter */
+int hsc_register_dvb(struct hsc_tsif *tsif);
+void hsc_unregister_dvb(struct hsc_tsif *tsif);
+int hsc_tsif_init(struct hsc_tsif *tsif, const struct hsc_conf *conf);
+void hsc_tsif_release(struct hsc_tsif *tsif);
+int hsc_dmaif_init(struct hsc_dmaif *dmaif, const struct hsc_conf *conf);
+void hsc_dmaif_release(struct hsc_dmaif *dmaif);
+extern const struct hsc_spec uniphier_hsc_ld11_spec;
+extern const struct hsc_spec uniphier_hsc_ld20_spec;
+
#endif /* DVB_UNIPHIER_HSC_H__ */
--
2.18.0
Adds code to load uCode and start the internal cores of HSC for
Socionext UniPhier SoCs.
Signed-off-by: Katsuhiro Suzuki <[email protected]>
---
Changes from v1:
- Split from large patches
- Fix include lines
---
drivers/media/platform/uniphier/Makefile | 2 +-
drivers/media/platform/uniphier/hsc-reg.h | 59 +++
drivers/media/platform/uniphier/hsc-ucode.c | 416 ++++++++++++++++++++
drivers/media/platform/uniphier/hsc.h | 4 +
4 files changed, 480 insertions(+), 1 deletion(-)
create mode 100644 drivers/media/platform/uniphier/hsc-ucode.c
diff --git a/drivers/media/platform/uniphier/Makefile b/drivers/media/platform/uniphier/Makefile
index 2ba03067644d..79b4dc44df94 100644
--- a/drivers/media/platform/uniphier/Makefile
+++ b/drivers/media/platform/uniphier/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-uniphier-dvb-y += hsc-dma.o hsc-css.o hsc-ts.o
+uniphier-dvb-y += hsc-dma.o hsc-css.o hsc-ts.o hsc-ucode.o
obj-$(CONFIG_DVB_UNIPHIER) += uniphier-dvb.o
diff --git a/drivers/media/platform/uniphier/hsc-reg.h b/drivers/media/platform/uniphier/hsc-reg.h
index 26f04b79178b..1ca3ad55330f 100644
--- a/drivers/media/platform/uniphier/hsc-reg.h
+++ b/drivers/media/platform/uniphier/hsc-reg.h
@@ -8,6 +8,65 @@
#ifndef DVB_UNIPHIER_HSC_REG_H__
#define DVB_UNIPHIER_HSC_REG_H__
+/* IOB1, 2, 3 */
+#define IOB_PKTCNT 0x1740
+#define IOB_PKTCNTRST 0x1744
+#define IOB_PKTCNTST 0x1744
+#define IOB_DUMMY_ENABLE 0x1748
+#define IOB_FORMATCHANGE_EN 0x174c
+#define IOB_UASSIST0 0x1750
+#define IOB_UASSIST1 0x1754
+#define IOB_URESERVE(i) (0x1758 + (i) * 0x4)
+#define IOB_PCRRECEN IOB_URESERVE(2)
+#define IOB_UPARTIAL(i) (0x1768 + (i) * 0x4)
+#define IOB_SPUINTREN 0x1778
+
+#define IOB_HSCREV 0x1a00
+#define IOB_SECCLK(i) (0x1a08 + (i) * 0x6c)
+#define IOB_SECTIMEH(i) (0x1a0c + (i) * 0x6c)
+#define IOB_SECTIMEL(i) (0x1a10 + (i) * 0x6c)
+#define IOB_RESET0 0x1a14
+#define IOB_RESET0_APCORE BIT(20)
+#define IOB_RESET1 0x1a18
+#define IOB_CLKSTOP 0x1a1c
+#define IOB_DEBUG 0x1a20
+#define IOB_DEBUG_SPUHALT BIT(0)
+#define IOB_INTREN(i) (0x1a24 + (i) * 0x8)
+#define IOB_INTRST(i) (0x1a28 + (i) * 0x8)
+#define IOB_INTREN0 0x1a24
+#define IOB_INTRST0 0x1a28
+#define IOB_INTREN0_1 0x1a2c
+#define IOB_INTRST0_1 0x1a30
+#define IOB_INTREN0_2 0x1a34
+#define IOB_INTRST0_2 0x1a38
+#define IOB_INTREN1 0x1a3c
+#define IOB_INTRST1 0x1a40
+#define IOB_INTREN1_1 0x1a44
+#define IOB_INTRST1_1 0x1a48
+#define IOB_INTREN2 0x1a4c
+#define IOB_INTRST2 0x1a50
+#define INTR2_DRV BIT(31)
+#define INTR2_CIP_FRMT(i) BIT((i) + 16)
+#define INTR2_CIP_NORMAL BIT(16)
+#define INTR2_SEC_CLK_A BIT(15)
+#define INTR2_SEC_CLK_S BIT(14)
+#define INTR2_MBC_CIP_W(i) BIT((i) + 9)
+#define INTR2_MBC_CIP_R(i) BIT((i) + 4)
+#define INTR2_CIP_AUTH_A BIT(1)
+#define INTR2_CIP_AUTH_S BIT(0)
+#define IOB_INTREN3 0x1a54
+#define IOB_INTRST3 0x1a58
+#define INTR3_DRV BIT(31)
+#define INTR3_CIP_FRMT(i) BIT((i) + 16)
+#define INTR3_SEC_CLK_A BIT(15)
+#define INTR3_SEC_CLK_S BIT(14)
+#define INTR3_MBC_CIP_W(i) BIT((i) + 9)
+#define INTR3_MBC_CIP_R(i) BIT((i) + 4)
+#define INTR3_CIP_AUTH_A BIT(1)
+#define INTR3_CIP_AUTH_S BIT(0)
+#define IOB_INTREN4 0x1a5c
+#define IOB_INTRST4 0x1a60
+
/* MBC1-7 Common */
#define CDMBC_STRT(i) (0x2300 + ((i) - 1) * 0x4)
#define CDMBC_PERFCNFG 0x230c
diff --git a/drivers/media/platform/uniphier/hsc-ucode.c b/drivers/media/platform/uniphier/hsc-ucode.c
new file mode 100644
index 000000000000..9d9369914c48
--- /dev/null
+++ b/drivers/media/platform/uniphier/hsc-ucode.c
@@ -0,0 +1,416 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext UniPhier DVB driver for High-speed Stream Controller (HSC).
+// Core init and uCode loader.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/bitfield.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+
+#include "hsc.h"
+#include "hsc-reg.h"
+
+/* CIP SPU File */
+#define CIP_F_ID 0x1540
+#define CIP_F_MODE 0x1544
+#define CIP_F_CTRL 0x1548
+#define CIP_F_SKIP 0x154c
+#define CIP_F_PAYLOAD 0x1560
+
+/* CIP file channel */
+#define CDMBC_CIPMODE(i) (0x24fc + (i) * 0x4)
+#define CDMBC_CIPMODE_PUSH BIT(0)
+#define CDMBC_CIPPRIORITY(i) (0x2510 + (i) * 0x4)
+#define CDMBC_CIPPRIORITY_PRIOR_MASK GENMASK(1, 0)
+#define CDMBC_CH18ATTRIBUTE (0x2524)
+
+/* UCODE DL */
+#define UCODE_REVISION_AM 0x10fd0
+#define CIP_UCODEADDR_AM1 0x10fd4
+#define CIP_UCODEADDR_AM0 0x10fd8
+#define CORRECTATS_CTRL 0x10fdc
+#define UCODE_REVISION 0x10fe0
+#define AM_UCODE_IGPGCTRL 0x10fe4
+#define REPDPLLCTRLEN 0x10fe8
+#define UCODE_DLADDR1 0x10fec
+#define UCODE_DLADDR0 0x10ff0
+#define UCODE_ERRLOGCTRL 0x10ff4
+
+struct hsc_cip_file_dma_param {
+ dma_addr_t cipr_start;
+ dma_addr_t cipw_start;
+ size_t inter_size;
+ size_t total_size;
+ u8 key_id1;
+ u8 key_id0;
+ u8 endian;
+ int id1_en;
+ int push;
+};
+
+static void core_start(struct hsc_chip *chip)
+{
+ const struct hsc_spec_init_ram *rams = chip->spec->init_rams;
+ struct regmap *r = chip->regmap;
+ size_t i, s;
+
+ regmap_write(r, IOB_RESET0, ~0);
+ regmap_write(r, IOB_RESET1, ~0);
+
+ regmap_write(r, IOB_CLKSTOP, 0);
+ /* Deassert all internal resets, but AP core is later for uCode */
+ regmap_write(r, IOB_RESET0, IOB_RESET0_APCORE);
+ regmap_write(r, IOB_RESET1, 0);
+
+ /* Halt SPU for uCode */
+ regmap_write(r, IOB_DEBUG, IOB_DEBUG_SPUHALT);
+
+ for (i = 0; i < chip->spec->num_init_rams; i++)
+ for (s = 0; s < rams[i].size; s += 4)
+ regmap_write(r, rams[i].addr + s, rams[i].pattern);
+}
+
+static void core_stop(struct hsc_chip *chip)
+{
+ struct regmap *r = chip->regmap;
+
+ regmap_write(r, IOB_RESET0, 0);
+ regmap_write(r, IOB_RESET1, 0);
+
+ regmap_write(r, IOB_CLKSTOP, ~0);
+}
+
+static int ucode_set_data_addr(struct hsc_chip *chip, int mode)
+{
+ struct regmap *r = chip->regmap;
+ dma_addr_t addr;
+
+ switch (mode) {
+ case HSC_UCODE_SPU_0:
+ case HSC_UCODE_SPU_1:
+ addr = chip->ucode_spu.phys_data;
+ regmap_write(r, UCODE_DLADDR0, addr);
+ regmap_write(r, UCODE_DLADDR1, addr >> 32);
+ break;
+ case HSC_UCODE_ACE:
+ addr = chip->ucode_am.phys_data;
+ regmap_write(r, CIP_UCODEADDR_AM0, addr);
+ regmap_write(r, CIP_UCODEADDR_AM1, addr >> 32);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void file_channel_dma_set(struct hsc_chip *chip,
+ const struct hsc_spec_dma *spec_r,
+ const struct hsc_spec_dma *spec_w,
+ struct hsc_cip_file_dma_param *p)
+{
+ struct regmap *r = chip->regmap;
+ dma_addr_t cipr_end, cipw_end;
+ u32 v;
+
+ /* For CIP Read */
+ v = FIELD_PREP(CDMBC_CHCTRL1_LINKCH1_MASK, 1) |
+ FIELD_PREP(CDMBC_CHCTRL1_STATSEL_MASK, 4) |
+ CDMBC_CHCTRL1_TYPE_INTERMIT;
+ regmap_write(r, CDMBC_CHCTRL1(spec_r->dma_ch), v);
+
+ regmap_write(r, CDMBC_CHCAUSECTRL(spec_r->dma_ch), 0);
+
+ v = FIELD_PREP(CDMBC_CHAMODE_ENDIAN_MASK, p->endian) |
+ FIELD_PREP(CDMBC_CHAMODE_AUPDT_MASK, 0) |
+ CDMBC_CHAMODE_TYPE_RB;
+ regmap_write(r, CDMBC_CHSRCAMODE(spec_r->dma_ch), v);
+
+ v = FIELD_PREP(CDMBC_CHAMODE_ENDIAN_MASK, 1) |
+ FIELD_PREP(CDMBC_CHAMODE_AUPDT_MASK, 2);
+ regmap_write(r, CDMBC_CHDSTAMODE(spec_r->dma_ch), v);
+
+ v = FIELD_PREP(CDMBC_CHDSTSTRTADRS_TID_MASK, 0xc) |
+ FIELD_PREP(CDMBC_CHDSTSTRTADRS_ID1_EN_MASK, p->id1_en) |
+ FIELD_PREP(CDMBC_CHDSTSTRTADRS_KEY_ID1_MASK, p->key_id1) |
+ FIELD_PREP(CDMBC_CHDSTSTRTADRS_KEY_ID0_MASK, p->key_id0);
+ regmap_write(r, CDMBC_CHDSTSTRTADRSD(spec_r->dma_ch), v);
+
+ regmap_write(r, CDMBC_CHSIZE(spec_r->dma_ch), p->inter_size);
+
+ cipr_end = p->cipr_start + p->total_size;
+ hsc_dma_rb_set_buffer(chip, spec_r->rb_ch, p->cipr_start, cipr_end);
+ hsc_dma_rb_set_rp(chip, spec_r->rb_ch, p->cipr_start);
+ hsc_dma_rb_set_wp(chip, spec_r->rb_ch, cipr_end);
+
+ /* For CIP Write */
+ v = FIELD_PREP(CDMBC_CHCTRL1_LINKCH1_MASK, 5) |
+ FIELD_PREP(CDMBC_CHCTRL1_STATSEL_MASK, 4) |
+ CDMBC_CHCTRL1_TYPE_INTERMIT |
+ CDMBC_CHCTRL1_IND_SIZE_UND;
+ regmap_write(r, CDMBC_CHCTRL1(spec_w->dma_ch), v);
+
+ v = FIELD_PREP(CDMBC_CHAMODE_ENDIAN_MASK, 1) |
+ FIELD_PREP(CDMBC_CHAMODE_AUPDT_MASK, 2);
+ regmap_write(r, CDMBC_CHSRCAMODE(spec_w->dma_ch), v);
+
+ v = FIELD_PREP(CDMBC_CHAMODE_ENDIAN_MASK, p->endian) |
+ FIELD_PREP(CDMBC_CHAMODE_AUPDT_MASK, 0) |
+ CDMBC_CHAMODE_TYPE_RB;
+ regmap_write(r, CDMBC_CHDSTAMODE(spec_w->dma_ch), v);
+
+ cipw_end = p->cipw_start + p->total_size;
+ hsc_dma_rb_set_buffer(chip, spec_w->rb_ch, p->cipw_start, cipw_end);
+ hsc_dma_rb_set_rp(chip, spec_w->rb_ch, cipw_end);
+ hsc_dma_rb_set_wp(chip, spec_w->rb_ch, p->cipw_start);
+
+ /* Transferring size */
+ regmap_write(r, CDMBC_ITSTEPS(spec_r->it_ch), p->total_size);
+
+ /* CIP settings */
+ regmap_write(r, CDMBC_CIPMODE(spec_r->cip_ch),
+ (p->push) ? CDMBC_CIPMODE_PUSH : 0);
+
+ regmap_write(r, CDMBC_CIPPRIORITY(spec_r->cip_ch),
+ FIELD_PREP(CDMBC_CIPPRIORITY_PRIOR_MASK, 3));
+}
+
+static void file_channel_start(struct hsc_chip *chip,
+ const struct hsc_spec_dma *spec_r,
+ const struct hsc_spec_dma *spec_w,
+ bool push, bool mmu_en)
+{
+ struct regmap *r = chip->regmap;
+ u32 v;
+
+ regmap_write(r, CDMBC_CIPMODE(spec_r->cip_ch),
+ (push) ? CDMBC_CIPMODE_PUSH : 0);
+
+ if (mmu_en) {
+ v = CDMBC_CHDDR_REG_LOAD_ON | CDMBC_CHDDR_AT_CHEN_ON;
+
+ /* Enable IOMMU for CIP-R and CIP-W */
+ regmap_write(r, CDMBC_CHDDR(spec_r->dma_ch),
+ v | CDMBC_CHDDR_SET_MCB_RD);
+ regmap_write(r, CDMBC_CHDDR(spec_w->dma_ch),
+ v | CDMBC_CHDDR_SET_MCB_WR);
+ }
+
+ v = 0x01000000 | (1 << spec_r->en.sft) | (1 << spec_w->en.sft);
+ regmap_write(r, CDMBC_STRT(1), v);
+}
+
+static void file_channel_wait(struct hsc_chip *chip,
+ const struct hsc_spec_dma *spec)
+{
+ struct regmap *r = chip->regmap;
+ u32 v;
+
+ regmap_read(r, CDMBC_CHIR(spec->dma_ch), &v);
+ while (!(v & INTR_MBC_CH_WDONE)) {
+ usleep_range(1000, 10000);
+ regmap_read(r, CDMBC_CHIR(spec->dma_ch), &v);
+ };
+ regmap_write(r, CDMBC_CHIR(spec->dma_ch), v);
+
+ regmap_read(r, CDMBC_RBIR(spec->dma_ch), &v);
+ regmap_write(r, CDMBC_RBIR(spec->dma_ch), v);
+}
+
+static int ucode_load_dma(struct hsc_chip *chip, int mode)
+{
+ const struct hsc_spec_dma *spec_r, *spec_w;
+ struct regmap *r = chip->regmap;
+ struct hsc_ucode_buf *ucode;
+ struct hsc_cip_file_dma_param dma_p = {0};
+ u32 cip_f_ctrl;
+
+ spec_r = &chip->spec->dma_in[HSC_DMA_CIP_IN0];
+ spec_w = &chip->spec->dma_out[HSC_DMA_CIP_OUT0];
+
+ switch (mode) {
+ case HSC_UCODE_SPU_0:
+ case HSC_UCODE_SPU_1:
+ ucode = &chip->ucode_spu;
+ cip_f_ctrl = 0x2f090001;
+ break;
+ case HSC_UCODE_ACE:
+ ucode = &chip->ucode_am;
+ cip_f_ctrl = 0x3f090001;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ regmap_write(r, CIP_F_CTRL, cip_f_ctrl);
+
+ dma_p.cipr_start = ucode->phys_code;
+ dma_p.cipw_start = 0;
+ dma_p.inter_size = ucode->size_code;
+ dma_p.total_size = ucode->size_code;
+ dma_p.key_id1 = 0;
+ dma_p.key_id0 = 0;
+ dma_p.endian = 1;
+ dma_p.id1_en = 0;
+ file_channel_dma_set(chip, spec_r, spec_w, &dma_p);
+ file_channel_start(chip, spec_r, spec_w, true, false);
+
+ file_channel_wait(chip, spec_r);
+ file_channel_wait(chip, spec_w);
+
+ return 0;
+}
+
+static int ucode_load(struct hsc_chip *chip, int mode)
+{
+ struct device *dev = &chip->pdev->dev;
+ const struct hsc_spec_ucode *spec;
+ struct hsc_ucode_buf *ucode;
+ const struct firmware *firm_code, *firm_data;
+ int ret;
+
+ switch (mode) {
+ case HSC_UCODE_SPU_0:
+ case HSC_UCODE_SPU_1:
+ spec = &chip->spec->ucode_spu;
+ ucode = &chip->ucode_spu;
+ break;
+ case HSC_UCODE_ACE:
+ spec = &chip->spec->ucode_ace;
+ ucode = &chip->ucode_am;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = request_firmware(&firm_code, spec->name_code, dev);
+ if (ret) {
+ dev_err(dev, "Failed to load firmware '%s'.\n",
+ spec->name_code);
+ return ret;
+ }
+
+ ret = request_firmware(&firm_data, spec->name_data, dev);
+ if (ret) {
+ dev_err(dev, "Failed to load firmware '%s'.\n",
+ spec->name_data);
+ goto err_firm_code;
+ }
+
+ ucode->buf_code = dma_alloc_coherent(dev, firm_code->size,
+ &ucode->phys_code, GFP_KERNEL);
+ if (!ucode->buf_code) {
+ ret = -ENOMEM;
+ goto err_firm_data;
+ }
+ ucode->size_code = firm_code->size;
+
+ ucode->buf_data = dma_alloc_coherent(dev, firm_data->size,
+ &ucode->phys_data, GFP_KERNEL);
+ if (!ucode->buf_data) {
+ ret = -ENOMEM;
+ goto err_buf_code;
+ }
+ ucode->size_data = firm_data->size;
+
+ memcpy(ucode->buf_code, firm_code->data, firm_code->size);
+ memcpy(ucode->buf_data, firm_data->data, firm_data->size);
+
+ ret = ucode_set_data_addr(chip, mode);
+ if (ret)
+ goto err_buf_data;
+
+ ret = ucode_load_dma(chip, mode);
+ if (ret)
+ goto err_buf_data;
+
+ release_firmware(firm_data);
+ release_firmware(firm_code);
+
+ return 0;
+
+err_buf_data:
+ dma_free_coherent(dev, ucode->size_data, ucode->buf_data,
+ ucode->phys_data);
+
+err_buf_code:
+ dma_free_coherent(dev, ucode->size_code, ucode->buf_code,
+ ucode->phys_code);
+
+err_firm_data:
+ release_firmware(firm_data);
+
+err_firm_code:
+ release_firmware(firm_code);
+
+ return ret;
+}
+
+static int ucode_unload(struct hsc_chip *chip, int mode)
+{
+ struct device *dev = &chip->pdev->dev;
+ struct hsc_ucode_buf *ucode;
+
+ switch (mode) {
+ case HSC_UCODE_SPU_0:
+ case HSC_UCODE_SPU_1:
+ ucode = &chip->ucode_spu;
+ break;
+ case HSC_UCODE_ACE:
+ ucode = &chip->ucode_am;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dma_free_coherent(dev, ucode->size_data, ucode->buf_data,
+ ucode->phys_data);
+ dma_free_coherent(dev, ucode->size_code, ucode->buf_code,
+ ucode->phys_code);
+
+ return 0;
+}
+
+int hsc_ucode_load_all(struct hsc_chip *chip)
+{
+ struct regmap *r = chip->regmap;
+ int ret;
+
+ core_start(chip);
+
+ ret = ucode_load(chip, HSC_UCODE_SPU_0);
+ if (ret)
+ return ret;
+
+ /* Start SPU core */
+ regmap_write(r, IOB_DEBUG, 0);
+
+ ret = ucode_load(chip, HSC_UCODE_ACE);
+ if (ret)
+ return ret;
+
+ /* Start AP core */
+ regmap_write(r, IOB_RESET0, 0);
+
+ return 0;
+}
+
+int hsc_ucode_unload_all(struct hsc_chip *chip)
+{
+ int ret;
+
+ core_stop(chip);
+
+ ret = ucode_unload(chip, HSC_UCODE_SPU_0);
+ if (ret)
+ return ret;
+
+ ret = ucode_unload(chip, HSC_UCODE_ACE);
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/drivers/media/platform/uniphier/hsc.h b/drivers/media/platform/uniphier/hsc.h
index a10b7a480193..bbfd90ffaad5 100644
--- a/drivers/media/platform/uniphier/hsc.h
+++ b/drivers/media/platform/uniphier/hsc.h
@@ -372,4 +372,8 @@ void hsc_dma_out_sync(struct hsc_dma *dma_out);
int hsc_dma_out_get_intr(struct hsc_dma *dma_out, u32 *stat);
void hsc_dma_out_clear_intr(struct hsc_dma *dma_out, u32 clear);
+/* UCODE DL */
+int hsc_ucode_load_all(struct hsc_chip *chip);
+int hsc_ucode_unload_all(struct hsc_chip *chip);
+
#endif /* DVB_UNIPHIER_HSC_H__ */
--
2.18.0
Add DMA code of HSC (High speed Stream Controller) driver for
Socionext UniPhier SoCs. The HSC enables to input and output
MPEG2-TS stream from/to outer world of SoC.
Signed-off-by: Katsuhiro Suzuki <[email protected]>
---
Changes from v1:
- Add COMPILE_TEST, REGMAP_MMIO
- Remove unneeded const
- Replace enum that has special value into #define
- Remove weird macro from register definitions
- Use shift and mask instead of field_get/prop inline functions
- Remove duplicated structures
- Fix depended config
- Fix include lines
---
drivers/media/platform/Kconfig | 1 +
drivers/media/platform/Makefile | 2 +
drivers/media/platform/uniphier/Kconfig | 11 +
drivers/media/platform/uniphier/Makefile | 4 +
drivers/media/platform/uniphier/hsc-dma.c | 212 +++++++++++++
drivers/media/platform/uniphier/hsc-reg.h | 118 ++++++++
drivers/media/platform/uniphier/hsc.h | 352 ++++++++++++++++++++++
7 files changed, 700 insertions(+)
create mode 100644 drivers/media/platform/uniphier/Kconfig
create mode 100644 drivers/media/platform/uniphier/Makefile
create mode 100644 drivers/media/platform/uniphier/hsc-dma.c
create mode 100644 drivers/media/platform/uniphier/hsc-reg.h
create mode 100644 drivers/media/platform/uniphier/hsc.h
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index e3079435565e..e7690fe3e7e4 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -528,6 +528,7 @@ menuconfig DVB_PLATFORM_DRIVERS
if DVB_PLATFORM_DRIVERS
source "drivers/media/platform/sti/c8sectpfe/Kconfig"
+source "drivers/media/platform/uniphier/Kconfig"
endif #DVB_PLATFORM_DRIVERS
menuconfig CEC_PLATFORM_DRIVERS
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 41322ab65802..ef763dac9d53 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -96,3 +96,5 @@ obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
obj-y += meson/
obj-y += cros-ec-cec/
+
+obj-$(CONFIG_DVB_UNIPHIER) += uniphier/
diff --git a/drivers/media/platform/uniphier/Kconfig b/drivers/media/platform/uniphier/Kconfig
new file mode 100644
index 000000000000..b96b98d98400
--- /dev/null
+++ b/drivers/media/platform/uniphier/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+config DVB_UNIPHIER
+ tristate "Socionext UniPhier Frontend"
+ depends on DVB_CORE && OF
+ depends on ARCH_UNIPHIER || COMPILE_TEST
+ select FW_LOADER
+ select REGMAP_MMIO
+ help
+ Driver for UniPhier frontend for MPEG2-TS input/output,
+ demux and descramble.
+ Say Y when you want to support this frontend.
diff --git a/drivers/media/platform/uniphier/Makefile b/drivers/media/platform/uniphier/Makefile
new file mode 100644
index 000000000000..c3d67a148dbe
--- /dev/null
+++ b/drivers/media/platform/uniphier/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+uniphier-dvb-y += hsc-dma.o
+
+obj-$(CONFIG_DVB_UNIPHIER) += uniphier-dvb.o
diff --git a/drivers/media/platform/uniphier/hsc-dma.c b/drivers/media/platform/uniphier/hsc-dma.c
new file mode 100644
index 000000000000..f5a58d81dffe
--- /dev/null
+++ b/drivers/media/platform/uniphier/hsc-dma.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext UniPhier DVB driver for High-speed Stream Controller (HSC).
+// MPEG2-TS DMA control.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/bitfield.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+
+#include "hsc.h"
+#include "hsc-reg.h"
+
+u64 hsc_rb_cnt(struct hsc_dma_buf *buf)
+{
+ if (buf->rd_offs <= buf->wr_offs)
+ return buf->wr_offs - buf->rd_offs;
+ else
+ return buf->size - (buf->rd_offs - buf->wr_offs);
+}
+
+u64 hsc_rb_cnt_to_end(struct hsc_dma_buf *buf)
+{
+ if (buf->rd_offs <= buf->wr_offs)
+ return buf->wr_offs - buf->rd_offs;
+ else
+ return buf->size - buf->rd_offs;
+}
+
+u64 hsc_rb_space(struct hsc_dma_buf *buf)
+{
+ if (buf->rd_offs <= buf->wr_offs)
+ return buf->size - (buf->wr_offs - buf->rd_offs) - 8;
+ else
+ return buf->rd_offs - buf->wr_offs - 8;
+}
+
+u64 hsc_rb_space_to_end(struct hsc_dma_buf *buf)
+{
+ if (buf->rd_offs > buf->wr_offs)
+ return buf->rd_offs - buf->wr_offs - 8;
+ else if (buf->rd_offs > 0)
+ return buf->size - buf->wr_offs;
+ else
+ return buf->size - buf->wr_offs - 8;
+}
+
+void hsc_dma_rb_set_buffer(struct hsc_chip *chip, int rb_ch, u64 bg, u64 ed)
+{
+ struct regmap *r = chip->regmap;
+
+ regmap_write(r, CDMBC_RBBGNADRSD(rb_ch), bg);
+ regmap_write(r, CDMBC_RBBGNADRSU(rb_ch), bg >> 32);
+ regmap_write(r, CDMBC_RBENDADRSD(rb_ch), ed);
+ regmap_write(r, CDMBC_RBENDADRSU(rb_ch), ed >> 32);
+}
+
+u64 hsc_dma_rb_get_rp(struct hsc_chip *chip, int rb_ch)
+{
+ struct regmap *r = chip->regmap;
+ u32 d, u;
+
+ regmap_read(r, CDMBC_RBRDPTRD(rb_ch), &d);
+ regmap_read(r, CDMBC_RBRDPTRU(rb_ch), &u);
+
+ return ((u64)u << 32) | d;
+}
+
+void hsc_dma_rb_set_rp(struct hsc_chip *chip, int rb_ch, u64 pos)
+{
+ struct regmap *r = chip->regmap;
+
+ regmap_write(r, CDMBC_RBRDPTRD(rb_ch), pos);
+ regmap_write(r, CDMBC_RBRDPTRU(rb_ch), pos >> 32);
+}
+
+u64 hsc_dma_rb_get_wp(struct hsc_chip *chip, int rb_ch)
+{
+ struct regmap *r = chip->regmap;
+ u32 d, u;
+
+ regmap_read(r, CDMBC_RBWRPTRD(rb_ch), &d);
+ regmap_read(r, CDMBC_RBWRPTRU(rb_ch), &u);
+
+ return ((u64)u << 32) | d;
+}
+
+void hsc_dma_rb_set_wp(struct hsc_chip *chip, int rb_ch, u64 pos)
+{
+ struct regmap *r = chip->regmap;
+
+ regmap_write(r, CDMBC_RBWRPTRD(rb_ch), pos);
+ regmap_write(r, CDMBC_RBWRPTRU(rb_ch), pos >> 32);
+}
+
+static void dma_set_chkp(struct hsc_chip *chip, int dma_ch, u64 pos)
+{
+ struct regmap *r = chip->regmap;
+
+ regmap_write(r, CDMBC_CHIRADRSD(dma_ch), pos);
+ regmap_write(r, CDMBC_CHIRADRSU(dma_ch), pos >> 32);
+}
+
+static void dma_set_enable(struct hsc_chip *chip, int dma_ch,
+ const struct hsc_reg_cmn *dma_en, bool en)
+{
+ struct regmap *r = chip->regmap;
+ u32 v;
+ bool now;
+
+ regmap_read(r, dma_en->reg, &v);
+ now = !!(v & BIT(dma_en->sft));
+
+ /* Toggle DMA state if needed */
+ if ((en && !now) || (!en && now))
+ regmap_write(r, dma_en->reg, BIT(dma_en->sft));
+}
+
+static bool dma_out_is_valid(struct hsc_chip *chip, int out)
+{
+ return out < chip->spec->num_dma_out ||
+ chip->spec->dma_out[out].intr.valid;
+}
+
+int hsc_dma_out_init(struct hsc_dma *dma_out, struct hsc_chip *chip,
+ int id, struct hsc_dma_buf *buf)
+{
+ if (!dma_out || !dma_out_is_valid(chip, id))
+ return -EINVAL;
+
+ dma_out->chip = chip;
+ dma_out->id = id;
+ dma_out->spec = &chip->spec->dma_out[id];
+ dma_out->buf = buf;
+
+ return 0;
+}
+
+void hsc_dma_out_set_src_ts_in(struct hsc_dma *dma_out, int tsi)
+{
+ struct regmap *r = dma_out->chip->regmap;
+ const struct hsc_spec_dma *spec = dma_out->spec;
+ u32 m, v;
+
+ m = CDMBC_CHTDCTRLH_STREM_MASK | CDMBC_CHTDCTRLH_ALL_EN;
+ v = FIELD_PREP(CDMBC_CHTDCTRLH_STREM_MASK, tsi) |
+ CDMBC_CHTDCTRLH_ALL_EN;
+ regmap_update_bits(r, CDMBC_CHTDCTRLH(spec->td_ch), m, v);
+}
+
+void hsc_dma_out_start(struct hsc_dma *dma_out, bool en)
+{
+ struct hsc_chip *chip = dma_out->chip;
+ const struct hsc_spec_dma *spec = dma_out->spec;
+ struct hsc_dma_buf *buf = dma_out->buf;
+ struct regmap *r = chip->regmap;
+ u64 bg, ed;
+ u32 v;
+
+ bg = buf->phys;
+ ed = buf->phys + buf->size;
+ hsc_dma_rb_set_buffer(chip, spec->rb_ch, bg, ed);
+
+ buf->rd_offs = 0;
+ buf->wr_offs = 0;
+ buf->chk_offs = buf->size_chk;
+ hsc_dma_rb_set_rp(chip, spec->rb_ch, buf->rd_offs + buf->phys);
+ hsc_dma_rb_set_wp(chip, spec->rb_ch, buf->wr_offs + buf->phys);
+ dma_set_chkp(chip, spec->dma_ch, buf->chk_offs + buf->phys);
+
+ regmap_update_bits(r, CDMBC_CHDSTAMODE(spec->dma_ch),
+ CDMBC_CHAMODE_TYPE_RB, ~0);
+ regmap_update_bits(r, CDMBC_CHCTRL1(spec->dma_ch),
+ CDMBC_CHCTRL1_IND_SIZE_UND, ~0);
+
+ v = (en) ? ~0 : 0;
+ regmap_update_bits(r, CDMBC_CHIE(spec->dma_ch), CDMBC_CHI_TRANSIT, v);
+ regmap_update_bits(r, spec->intr.reg, BIT(spec->intr.sft), v);
+
+ dma_set_enable(chip, spec->dma_ch, &spec->en, en);
+}
+
+void hsc_dma_out_sync(struct hsc_dma *dma_out)
+{
+ struct hsc_chip *chip = dma_out->chip;
+ const struct hsc_spec_dma *spec = dma_out->spec;
+ struct hsc_dma_buf *buf = dma_out->buf;
+
+ hsc_dma_rb_set_rp(chip, spec->rb_ch, buf->rd_offs + buf->phys);
+ buf->wr_offs = hsc_dma_rb_get_wp(chip, spec->rb_ch) - buf->phys;
+ dma_set_chkp(chip, spec->dma_ch, buf->chk_offs + buf->phys);
+}
+
+int hsc_dma_out_get_intr(struct hsc_dma *dma_out, u32 *stat)
+{
+ struct regmap *r = dma_out->chip->regmap;
+
+ if (!stat)
+ return -EINVAL;
+
+ regmap_read(r, CDMBC_CHID(dma_out->spec->dma_ch), stat);
+
+ return 0;
+}
+
+void hsc_dma_out_clear_intr(struct hsc_dma *dma_out, u32 clear)
+{
+ struct regmap *r = dma_out->chip->regmap;
+
+ regmap_write(r, CDMBC_CHIR(dma_out->spec->dma_ch), clear);
+}
diff --git a/drivers/media/platform/uniphier/hsc-reg.h b/drivers/media/platform/uniphier/hsc-reg.h
new file mode 100644
index 000000000000..2d87960c9b97
--- /dev/null
+++ b/drivers/media/platform/uniphier/hsc-reg.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Socionext UniPhier DVB driver for High-speed Stream Controller (HSC).
+ *
+ * Copyright (c) 2018 Socionext Inc.
+ */
+
+#ifndef DVB_UNIPHIER_HSC_REG_H__
+#define DVB_UNIPHIER_HSC_REG_H__
+
+/* MBC1-7 Common */
+#define CDMBC_STRT(i) (0x2300 + ((i) - 1) * 0x4)
+#define CDMBC_PERFCNFG 0x230c
+#define CDMBC_STAT(i) (0x2320 + (i) * 0x4)
+#define CDMBC_PARTRESET(i) (0x234c + (i) * 0x4)
+#define CDMBC_MONNUM 0x2358
+#define CDMBC_MONDAT 0x235c
+#define CDMBC_PRC0CHIE0 0x2380
+#define CDMBC_PRC0RBIE0 0x2384
+#define CDMBC_PRC1CHIE0 0x2388
+#define CDMBC_PRC2CHIE0 0x2390
+#define CDMBC_PRC2RBIE0 0x2394
+#define CDMBC_SOFTFLRQ 0x239c
+#define CDMBC_TDSTRT 0x23a0
+
+#define INTR_MBC_CH_END BIT(15)
+#define INTR_MBC_CH_STOP BIT(13)
+#define INTR_MBC_CH_ADDR BIT(6)
+#define INTR_MBC_CH_IWDONE BIT(3)
+#define INTR_MBC_CH_WDONE BIT(1)
+
+/* MBC DMA channel, only for output DMA */
+#define CDMBC_CHTDCTRLH(i) (0x23a4 + (i) * 0x10)
+#define CDMBC_CHTDCTRLH_STREM_MASK GENMASK(20, 16)
+#define CDMBC_CHTDCTRLH_NOT_FLT BIT(7)
+#define CDMBC_CHTDCTRLH_ALL_EN BIT(6)
+#define CDMBC_CHTDCTRLU(i) (0x23a8 + (i) * 0x10)
+
+/* MBC DMA channel */
+#define CDMBC_CHCTRL1(i) (0x2540 + (i) * 0x50)
+#define CDMBC_CHCTRL1_LINKCH1_MASK GENMASK(12, 10)
+#define CDMBC_CHCTRL1_STATSEL_MASK GENMASK(9, 7)
+#define CDMBC_CHCTRL1_TYPE_INTERMIT BIT(1)
+#define CDMBC_CHCTRL1_IND_SIZE_UND BIT(0)
+#define CDMBC_CHCTRL2(i) (0x2544 + (i) * 0x50)
+#define CDMBC_CHDDR(i) (0x2548 + (i) * 0x50)
+#define CDMBC_CHDDR_REG_LOAD_ON BIT(4)
+#define CDMBC_CHDDR_AT_CHEN_ON BIT(3)
+#define CDMBC_CHDDR_SET_MCB_MASK GENMASK(2, 1)
+#define CDMBC_CHDDR_SET_MCB_WR (0x0 << 1)
+#define CDMBC_CHDDR_SET_MCB_RD (0x3 << 1)
+#define CDMBC_CHDDR_SET_DDR_1 BIT(0)
+#define CDMBC_CHCAUSECTRL(i) (0x254c + (i) * 0x50)
+#define CDMBC_CHCAUSECTRL_MODE_MASK BIT(31)
+#define CDMBC_CHCAUSECTRL_CSEL2_MASK GENMASK(20, 12)
+#define CDMBC_CHCAUSECTRL_CSEL1_MASK GENMASK(8, 0)
+#define CDMBC_CHSTAT(i) (0x2550 + (i) * 0x50)
+#define CDMBC_CHIR(i) (0x2554 + (i) * 0x50)
+#define CDMBC_CHIE(i) (0x2558 + (i) * 0x50)
+#define CDMBC_CHID(i) (0x255c + (i) * 0x50)
+#define CDMBC_CHI_STOPPED BIT(13)
+#define CDMBC_CHI_TRANSIT BIT(6)
+#define CDMBC_CHI_STARTING BIT(1)
+#define CDMBC_CHSRCAMODE(i) (0x2560 + (i) * 0x50)
+#define CDMBC_CHDSTAMODE(i) (0x2564 + (i) * 0x50)
+#define CDMBC_CHAMODE_TUNIT_MASK GENMASK(29, 28)
+#define CDMBC_CHAMODE_ENDIAN_MASK GENMASK(17, 16)
+#define CDMBC_CHAMODE_AUPDT_MASK GENMASK(5, 4)
+#define CDMBC_CHAMODE_TYPE_RB BIT(2)
+#define CDMBC_CHSRCSTRTADRSD(i) (0x2568 + (i) * 0x50)
+#define CDMBC_CHSRCSTRTADRSU(i) (0x256c + (i) * 0x50)
+#define CDMBC_CHDSTSTRTADRSD(i) (0x2570 + (i) * 0x50)
+#define CDMBC_CHDSTSTRTADRSU(i) (0x2574 + (i) * 0x50)
+#define CDMBC_CHDSTSTRTADRS_TID_MASK GENMASK(31, 28)
+#define CDMBC_CHDSTSTRTADRS_ID1_EN_MASK BIT(15)
+#define CDMBC_CHDSTSTRTADRS_KEY_ID1_MASK GENMASK(12, 8)
+#define CDMBC_CHDSTSTRTADRS_KEY_ID0_MASK GENMASK(4, 0)
+#define CDMBC_CHSIZE(i) (0x2578 + (i) * 0x50)
+#define CDMBC_CHIRADRSD(i) (0x2580 + (i) * 0x50)
+#define CDMBC_CHIRADRSU(i) (0x2584 + (i) * 0x50)
+#define CDMBC_CHDST1STUSIZE(i) (0x258C + (i) * 0x50)
+
+/* MBC DMA intermit transfer, only for input DMA */
+#define CDMBC_ITCTRL(i) (0x3000 + (i) * 0x20)
+#define CDMBC_ITSTEPS(i) (0x3018 + (i) * 0x20)
+
+/* MBC ring buffer */
+#define CDMBC_RBBGNADRS(i) (0x3200 + (i) * 0x40)
+#define CDMBC_RBBGNADRSD(i) (0x3200 + (i) * 0x40)
+#define CDMBC_RBBGNADRSU(i) (0x3204 + (i) * 0x40)
+#define CDMBC_RBENDADRS(i) (0x3208 + (i) * 0x40)
+#define CDMBC_RBENDADRSD(i) (0x3208 + (i) * 0x40)
+#define CDMBC_RBENDADRSU(i) (0x320C + (i) * 0x40)
+#define CDMBC_RBIR(i) (0x3214 + (i) * 0x40)
+#define CDMBC_RBIE(i) (0x3218 + (i) * 0x40)
+#define CDMBC_RBID(i) (0x321c + (i) * 0x40)
+#define CDMBC_RBRDPTR(i) (0x3220 + (i) * 0x40)
+#define CDMBC_RBRDPTRD(i) (0x3220 + (i) * 0x40)
+#define CDMBC_RBRDPTRU(i) (0x3224 + (i) * 0x40)
+#define CDMBC_RBWRPTR(i) (0x3228 + (i) * 0x40)
+#define CDMBC_RBWRPTRD(i) (0x3228 + (i) * 0x40)
+#define CDMBC_RBWRPTRU(i) (0x322C + (i) * 0x40)
+#define CDMBC_RBERRCNFG(i) (0x3238 + (i) * 0x40)
+
+/* MBC Rate */
+#define CDMBC_RCNMSKCYC(i) (MBC6_TOP_ADDR + 0x000 + (i) * 0x04)
+
+/* MBC Address Transfer */
+#define CDMBC_CHPSIZE(i) (0x3c00 + ((i) - 1) * 0x48)
+#define CDMBC_CHATCTRL(i) (0x3c04 + ((i) - 1) * 0x48)
+#define CDMBC_CHBTPAGE(i, j) (0x3c08 + ((i) - 1) * 0x48 + (j) * 0x10)
+#define CDMBC_CHBTPAGED(i, j) (0x3c08 + ((i) - 1) * 0x48 + (j) * 0x10)
+#define CDMBC_CHBTPAGEU(i, j) (0x3c0C + ((i) - 1) * 0x48 + (j) * 0x10)
+#define CDMBC_CHATPAGE(i, j) (0x3c10 + ((i) - 1) * 0x48 + (j) * 0x10)
+#define CDMBC_CHATPAGED(i, j) (0x3c10 + ((i) - 1) * 0x48 + (j) * 0x10)
+#define CDMBC_CHATPAGEU(i, j) (0x3c14 + ((i) - 1) * 0x48 + (j) * 0x10)
+
+#endif /* DVB_UNIPHIER_HSC_REG_H__ */
diff --git a/drivers/media/platform/uniphier/hsc.h b/drivers/media/platform/uniphier/hsc.h
new file mode 100644
index 000000000000..fddc66df81c7
--- /dev/null
+++ b/drivers/media/platform/uniphier/hsc.h
@@ -0,0 +1,352 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Socionext UniPhier DVB driver for High-speed Stream Controller (HSC).
+ *
+ * Copyright (c) 2018 Socionext Inc.
+ */
+
+#ifndef DVB_UNIPHIER_HSC_H__
+#define DVB_UNIPHIER_HSC_H__
+
+#include <linux/gpio/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include <media/dmxdev.h>
+#include <media/dvbdev.h>
+#include <media/dvb_demux.h>
+#include <media/dvb_frontend.h>
+
+enum {
+ HSC_CORE_0,
+ HSC_CORE_1,
+ HSC_CORE_2,
+};
+
+enum {
+ HSC_UCODE_SPU_0,
+ HSC_UCODE_SPU_1,
+ HSC_UCODE_ACE,
+};
+
+enum {
+ HSC_TSIF_MPEG2_TS,
+ HSC_TSIF_MPEG2_TS_ATS,
+};
+
+/* DPLL */
+#define HSC_DPLL0 0
+#define HSC_DPLL1 1
+#define HSC_DPLL2 2
+#define HSC_DPLL3 3
+
+#define HSC_DPLL_NUM 4
+
+/* Clock source of DPLL */
+#define HSC_DPLL_SRC_NONE -1
+#define HSC_DPLL_SRC_TSI0 0
+#define HSC_DPLL_SRC_TSI1 1
+#define HSC_DPLL_SRC_TSI2 2
+#define HSC_DPLL_SRC_TSI3 3
+#define HSC_DPLL_SRC_TSI4 4
+#define HSC_DPLL_SRC_TSI5 5
+#define HSC_DPLL_SRC_TSI6 6
+#define HSC_DPLL_SRC_TSI7 7
+#define HSC_DPLL_SRC_TSI8 8
+#define HSC_DPLL_SRC_TSI9 9
+#define HSC_DPLL_SRC_REP0 10
+#define HSC_DPLL_SRC_REP1 11
+#define HSC_DPLL_SRC_REP2 12
+#define HSC_DPLL_SRC_REP3 13
+#define HSC_DPLL_SRC_REP4 14
+#define HSC_DPLL_SRC_REP5 15
+
+#define HSC_DPLL_SRC_NUM 16
+
+/* Port to send to CSS */
+#define HSC_CSS_IN_1394_0 0
+#define HSC_CSS_IN_1394_1 1
+#define HSC_CSS_IN_1394_2 2
+#define HSC_CSS_IN_1394_3 3
+#define HSC_CSS_IN_DMD0 4
+#define HSC_CSS_IN_DMD1 5
+#define HSC_CSS_IN_SRLTS0 6
+#define HSC_CSS_IN_SRLTS1 7
+#define HSC_CSS_IN_SRLTS2 8
+#define HSC_CSS_IN_SRLTS3 9
+#define HSC_CSS_IN_SRLTS4 10
+#define HSC_CSS_IN_SRLTS5 11
+#define HSC_CSS_IN_SRLTS6 12
+#define HSC_CSS_IN_SRLTS7 13
+#define HSC_CSS_IN_PARTS0 16
+#define HSC_CSS_IN_PARTS1 17
+#define HSC_CSS_IN_PARTS2 18
+#define HSC_CSS_IN_PARTS3 19
+#define HSC_CSS_IN_TSO0 24
+#define HSC_CSS_IN_TSO1 25
+#define HSC_CSS_IN_TSO2 26
+#define HSC_CSS_IN_TSO3 27
+#define HSC_CSS_IN_ENCORDER0_IN 28
+#define HSC_CSS_IN_ENCORDER1_IN 29
+
+/* Port to receive from CSS */
+#define HSC_CSS_OUT_SRLTS0 0
+#define HSC_CSS_OUT_SRLTS1 1
+#define HSC_CSS_OUT_SRLTS2 2
+#define HSC_CSS_OUT_SRLTS3 3
+#define HSC_CSS_OUT_TSI0 4
+#define HSC_CSS_OUT_TSI1 5
+#define HSC_CSS_OUT_TSI2 6
+#define HSC_CSS_OUT_TSI3 7
+#define HSC_CSS_OUT_TSI4 8
+#define HSC_CSS_OUT_TSI5 9
+#define HSC_CSS_OUT_TSI6 10
+#define HSC_CSS_OUT_TSI7 11
+#define HSC_CSS_OUT_TSI8 12
+#define HSC_CSS_OUT_TSI9 13
+#define HSC_CSS_OUT_PARTS0 16
+#define HSC_CSS_OUT_PARTS1 17
+#define HSC_CSS_OUT_PKTFF0 20
+#define HSC_CSS_OUT_PKTFF1 21
+
+/* TS input interface */
+#define HSC_TS_IN0 0
+#define HSC_TS_IN1 1
+#define HSC_TS_IN2 2
+#define HSC_TS_IN3 3
+#define HSC_TS_IN4 4
+#define HSC_TS_IN5 5
+#define HSC_TS_IN6 6
+#define HSC_TS_IN7 7
+#define HSC_TS_IN8 8
+#define HSC_TS_IN9 9
+
+/* TS output interface */
+#define HSC_TS_OUT0 0
+#define HSC_TS_OUT1 1
+#define HSC_TS_OUT2 2
+#define HSC_TS_OUT3 3
+#define HSC_TS_OUT4 4
+#define HSC_TS_OUT5 5
+#define HSC_TS_OUT6 6
+#define HSC_TS_OUT7 7
+#define HSC_TS_OUT8 8
+#define HSC_TS_OUT9 9
+
+/* DMA to read from memory (Replay DMA) */
+#define HSC_DMA_IN0 0
+#define HSC_DMA_IN1 1
+#define HSC_DMA_IN2 2
+#define HSC_DMA_IN3 3
+#define HSC_DMA_IN4 4
+#define HSC_DMA_IN5 5
+#define HSC_DMA_IN6 6
+#define HSC_DMA_IN7 7
+#define HSC_DMA_IN8 8
+#define HSC_DMA_IN9 9
+#define HSC_DMA_CIP_IN0 10
+#define HSC_DMA_CIP_IN1 11
+
+/* DMA to write to memory (Record DMA) */
+#define HSC_DMA_OUT0 0
+#define HSC_DMA_OUT1 1
+#define HSC_DMA_OUT2 2
+#define HSC_DMA_OUT3 3
+#define HSC_DMA_OUT4 4
+#define HSC_DMA_OUT5 5
+#define HSC_DMA_OUT6 6
+#define HSC_DMA_OUT7 7
+#define HSC_DMA_OUT8 8
+#define HSC_DMA_OUT9 9
+#define HSC_DMA_CIP_OUT0 10
+#define HSC_DMA_CIP_OUT1 11
+
+#define HSC_STREAM_IF_NUM 2
+
+#define HSC_DMAIF_TS_BUFSIZE (192 * 1024 * 5)
+
+struct hsc_ucode_buf {
+ void *buf_code;
+ dma_addr_t phys_code;
+ size_t size_code;
+ void *buf_data;
+ dma_addr_t phys_data;
+ size_t size_data;
+};
+
+struct hsc_spec_ucode {
+ const char *name_code;
+ const char *name_data;
+};
+
+struct hsc_spec_init_ram {
+ u32 addr;
+ size_t size;
+ u32 pattern;
+};
+
+struct hsc_reg_cmn {
+ int valid;
+ u32 reg;
+ int sft;
+};
+
+struct hsc_reg_css_pol {
+ int valid;
+ u32 reg;
+ int sft_sync;
+ int sft_val;
+ int sft_clk;
+};
+
+struct hsc_reg_css_sel {
+ int valid;
+ u32 reg;
+ u32 mask;
+ int sft;
+};
+
+struct hsc_spec_css {
+ struct hsc_reg_css_pol pol;
+ struct hsc_reg_css_sel sel;
+};
+
+struct hsc_spec_ts {
+ struct hsc_reg_cmn intr;
+};
+
+struct hsc_spec_dma {
+ /* DMA channel for CDMBC_CH* registers */
+ int dma_ch;
+ /* Ring buffer channel for CDMBC_RB* registers */
+ int rb_ch;
+ /* CIP file channel for CDMBC_CIP* registers */
+ int cip_ch;
+ /* Intermit transfer channel for CDMBC_IT* registers */
+ int it_ch;
+ /* DMA channel (output only) for CDMBC_CHTDCTR* registers */
+ int td_ch;
+ struct hsc_reg_cmn en;
+ struct hsc_reg_cmn intr;
+
+};
+
+struct hsc_spec {
+ struct hsc_spec_ucode ucode_spu;
+ struct hsc_spec_ucode ucode_ace;
+ const struct hsc_spec_init_ram *init_rams;
+ size_t num_init_rams;
+ const struct hsc_spec_css *css_in;
+ size_t num_css_in;
+ const struct hsc_spec_css *css_out;
+ size_t num_css_out;
+ const struct hsc_spec_ts *ts_in;
+ size_t num_ts_in;
+ const struct hsc_spec_dma *dma_in;
+ size_t num_dma_in;
+ const struct hsc_spec_dma *dma_out;
+ size_t num_dma_out;
+};
+
+struct hsc_tsif {
+ struct hsc_chip *chip;
+
+ struct dvb_adapter adapter;
+ struct dvb_demux demux;
+ struct dmxdev dmxdev;
+ struct dvb_frontend *fe;
+ int valid_adapter;
+ int valid_demux;
+ int valid_dmxdev;
+ int valid_fe;
+
+ int css_in;
+ int css_out;
+ int tsi;
+ int dpll;
+ int dpll_src;
+ struct hsc_dmaif *dmaif;
+
+ int running;
+ struct delayed_work recover_work;
+ unsigned long recover_delay;
+};
+
+struct hsc_dma {
+ struct hsc_chip *chip;
+
+ int id;
+ const struct hsc_spec_dma *spec;
+ struct hsc_dma_buf *buf;
+};
+
+struct hsc_dma_buf {
+ void *virt;
+ dma_addr_t phys;
+ u64 size;
+ u64 size_chk;
+ u64 rd_offs;
+ u64 wr_offs;
+ u64 chk_offs;
+};
+
+struct hsc_dmaif {
+ struct hsc_chip *chip;
+
+ struct hsc_dma_buf buf_out;
+ struct hsc_dma dma_out;
+
+ struct hsc_tsif *tsif;
+
+ /* guard read/write pointer of DMA buffer from interrupt handler */
+ spinlock_t lock;
+ int running;
+ struct work_struct feed_work;
+};
+
+struct hsc_chip {
+ const struct hsc_spec *spec;
+ short *adapter_nums;
+
+ struct platform_device *pdev;
+ struct regmap *regmap;
+ struct clk *clk_stdmac;
+ struct clk *clk_hsc;
+ struct reset_control *rst_stdmac;
+ struct reset_control *rst_hsc;
+
+ struct hsc_dmaif dmaif[HSC_STREAM_IF_NUM];
+ struct hsc_tsif tsif[HSC_STREAM_IF_NUM];
+
+ struct hsc_ucode_buf ucode_spu;
+ struct hsc_ucode_buf ucode_am;
+};
+
+struct hsc_conf {
+ int css_in;
+ int css_out;
+ int dpll;
+ int dma_out;
+};
+
+/* DMA */
+u64 hsc_rb_cnt(struct hsc_dma_buf *buf);
+u64 hsc_rb_cnt_to_end(struct hsc_dma_buf *buf);
+u64 hsc_rb_space(struct hsc_dma_buf *buf);
+u64 hsc_rb_space_to_end(struct hsc_dma_buf *buf);
+
+void hsc_dma_rb_set_buffer(struct hsc_chip *chip, int rb_ch, u64 bg, u64 ed);
+u64 hsc_dma_rb_get_rp(struct hsc_chip *chip, int rb_ch);
+void hsc_dma_rb_set_rp(struct hsc_chip *chip, int rb_ch, u64 pos);
+u64 hsc_dma_rb_get_wp(struct hsc_chip *chip, int rb_ch);
+void hsc_dma_rb_set_wp(struct hsc_chip *chip, int rb_ch, u64 pos);
+
+int hsc_dma_out_init(struct hsc_dma *dma_out, struct hsc_chip *chip,
+ int id, struct hsc_dma_buf *buf);
+void hsc_dma_out_set_src_ts_in(struct hsc_dma *dma_out, int tsi);
+void hsc_dma_out_start(struct hsc_dma *dma_out, bool en);
+void hsc_dma_out_sync(struct hsc_dma *dma_out);
+int hsc_dma_out_get_intr(struct hsc_dma *dma_out, u32 *stat);
+void hsc_dma_out_clear_intr(struct hsc_dma *dma_out, u32 clear);
+
+#endif /* DVB_UNIPHIER_HSC_H__ */
--
2.18.0
Add CSS (Cross Stream Switch) code for connecting and switching the
MPEG2-TS stream path of inner cores of HSC for Socionext UniPhier
SoCs.
Signed-off-by: Katsuhiro Suzuki <[email protected]>
---
Changes from v1:
- Split from large patches
- Fix include lines
- Remove redundant conditions
---
drivers/media/platform/uniphier/Makefile | 2 +-
drivers/media/platform/uniphier/hsc-css.c | 250 ++++++++++++++++++++++
drivers/media/platform/uniphier/hsc-reg.h | 29 +++
drivers/media/platform/uniphier/hsc.h | 17 ++
4 files changed, 297 insertions(+), 1 deletion(-)
create mode 100644 drivers/media/platform/uniphier/hsc-css.c
diff --git a/drivers/media/platform/uniphier/Makefile b/drivers/media/platform/uniphier/Makefile
index c3d67a148dbe..59be2edf0c53 100644
--- a/drivers/media/platform/uniphier/Makefile
+++ b/drivers/media/platform/uniphier/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-uniphier-dvb-y += hsc-dma.o
+uniphier-dvb-y += hsc-dma.o hsc-css.o
obj-$(CONFIG_DVB_UNIPHIER) += uniphier-dvb.o
diff --git a/drivers/media/platform/uniphier/hsc-css.c b/drivers/media/platform/uniphier/hsc-css.c
new file mode 100644
index 000000000000..0ab8156b0ffd
--- /dev/null
+++ b/drivers/media/platform/uniphier/hsc-css.c
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext UniPhier DVB driver for High-speed Stream Controller (HSC).
+// CSS (Cross Stream Switch) connects MPEG2-TS input port and output port.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/bitfield.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+
+#include "hsc.h"
+#include "hsc-reg.h"
+
+int hsc_css_out_to_ts_in(int out)
+{
+ if (out >= HSC_CSS_OUT_TSI0 && out <= HSC_CSS_OUT_TSI9)
+ return HSC_TS_IN0 + (out - HSC_CSS_OUT_TSI0);
+
+ return -1;
+}
+
+int hsc_css_out_to_dpll_src(int out)
+{
+ if (out >= HSC_CSS_OUT_TSI0 && out <= HSC_CSS_OUT_TSI9)
+ return HSC_DPLL_SRC_TSI0 + (out - HSC_CSS_OUT_TSI0);
+
+ return -1;
+}
+
+static bool css_in_is_valid(struct hsc_chip *chip, int in)
+{
+ return in < chip->spec->num_css_in;
+}
+
+static bool css_out_is_valid(struct hsc_chip *chip, int out)
+{
+ return out < chip->spec->num_css_out;
+}
+
+static const struct hsc_spec_css *css_in_get_spec(struct hsc_chip *chip,
+ int in)
+{
+ const struct hsc_spec_css *spec = chip->spec->css_in;
+
+ if (!css_in_is_valid(chip, in))
+ return NULL;
+
+ return &spec[in];
+}
+
+static const struct hsc_spec_css *css_out_get_spec(struct hsc_chip *chip,
+ int out)
+{
+ const struct hsc_spec_css *spec = chip->spec->css_out;
+
+ if (!css_out_is_valid(chip, out))
+ return NULL;
+
+ return &spec[out];
+}
+
+int hsc_dpll_get_src(struct hsc_chip *chip, int dpll, int *src)
+{
+ struct regmap *r = chip->regmap;
+ u32 v;
+
+ if (!src || dpll >= HSC_DPLL_NUM)
+ return -EINVAL;
+
+ regmap_read(r, CSS_DPCTRL(dpll), &v);
+ *src = ffs(v & CSS_DPCTRL_DPSEL_MASK) - 1;
+
+ return 0;
+}
+
+/**
+ * Select source clock of DPLL.
+ *
+ * @dpll: ID of DPLL, use one of HSC_DPLL_*
+ * @src : ID of clock source, use one of HSC_DPLL_SRC_* or HSC_DPLL_SRC_NONE
+ * to disconnect
+ */
+int hsc_dpll_set_src(struct hsc_chip *chip, int dpll, int src)
+{
+ struct regmap *r = chip->regmap;
+ u32 v = 0;
+
+ if (dpll >= HSC_DPLL_NUM || src >= HSC_DPLL_SRC_NUM)
+ return -EINVAL;
+
+ if (src != HSC_DPLL_SRC_NONE)
+ v = 1 << src;
+
+ regmap_write(r, CSS_DPCTRL(dpll), v);
+
+ return 0;
+}
+
+static int hsc_css_get_polarity(struct hsc_chip *chip,
+ const struct hsc_reg_css_pol *pol,
+ bool *sync_bit, bool *val_bit, bool *clk_fall)
+{
+ struct regmap *r = chip->regmap;
+ u32 v;
+
+ if (!sync_bit || !val_bit || !clk_fall || !pol->valid)
+ return -EINVAL;
+
+ regmap_read(r, pol->reg, &v);
+
+ *sync_bit = !!(v & BIT(pol->sft_sync));
+ *val_bit = !!(v & BIT(pol->sft_val));
+ *clk_fall = !!(v & BIT(pol->sft_clk));
+
+ return 0;
+}
+
+/**
+ * Setup signal polarity of TS signals.
+ *
+ * @sync_bit : true : The sync signal keeps only 1bit period.
+ * false: The sync signal keeps during 8bits period.
+ * @valid_bit: true : The valid signal does not keep during 8bits period.
+ * false: The valid signal keeps during 8bits period.
+ * @clk_fall : true : Latch the data at falling edge of clock signal.
+ * false: Latch the data at rising edge of clock signal.
+ */
+static int hsc_css_set_polarity(struct hsc_chip *chip,
+ const struct hsc_reg_css_pol *pol,
+ bool sync_bit, bool val_bit, bool clk_fall)
+{
+ struct regmap *r = chip->regmap;
+ u32 m = 0, v = 0;
+
+ if (!pol->valid)
+ return -EINVAL;
+
+ if (pol->sft_sync != -1) {
+ m |= BIT(pol->sft_sync);
+ if (sync_bit)
+ v |= BIT(pol->sft_sync);
+ }
+
+ if (pol->sft_val != -1) {
+ m |= BIT(pol->sft_val);
+ if (val_bit)
+ v |= BIT(pol->sft_val);
+ }
+
+ if (pol->sft_clk != -1) {
+ m |= BIT(pol->sft_clk);
+ if (clk_fall)
+ v |= BIT(pol->sft_clk);
+ }
+
+ regmap_update_bits(r, pol->reg, m, v);
+
+ return 0;
+}
+
+int hsc_css_in_get_polarity(struct hsc_chip *chip, int in,
+ bool *sync_bit, bool *val_bit, bool *clk_fall)
+{
+ const struct hsc_spec_css *speci = css_in_get_spec(chip, in);
+
+ if (!speci)
+ return -EINVAL;
+
+ return hsc_css_get_polarity(chip, &speci->pol,
+ sync_bit, val_bit, clk_fall);
+}
+
+int hsc_css_in_set_polarity(struct hsc_chip *chip, int in,
+ bool sync_bit, bool val_bit, bool clk_fall)
+{
+ const struct hsc_spec_css *speci = css_in_get_spec(chip, in);
+
+ if (!speci)
+ return -EINVAL;
+
+ return hsc_css_set_polarity(chip, &speci->pol,
+ sync_bit, val_bit, clk_fall);
+}
+
+int hsc_css_out_get_polarity(struct hsc_chip *chip, int out,
+ bool *sync_bit, bool *val_bit, bool *clk_fall)
+{
+ const struct hsc_spec_css *speco = css_out_get_spec(chip, out);
+
+ if (!speco)
+ return -EINVAL;
+
+ return hsc_css_get_polarity(chip, &speco->pol,
+ sync_bit, val_bit, clk_fall);
+}
+
+int hsc_css_out_set_polarity(struct hsc_chip *chip, int out,
+ bool sync_bit, bool val_bit, bool clk_fall)
+{
+ const struct hsc_spec_css *speco = css_out_get_spec(chip, out);
+
+ if (!speco)
+ return -EINVAL;
+
+ return hsc_css_set_polarity(chip, &speco->pol,
+ sync_bit, val_bit, clk_fall);
+}
+
+int hsc_css_out_get_src(struct hsc_chip *chip, int *tsi, int out, bool *en)
+{
+ struct regmap *r = chip->regmap;
+ const struct hsc_spec_css *speco = css_out_get_spec(chip, out);
+ u32 v;
+
+ if (!tsi || !en || !speco || !speco->sel.valid)
+ return -EINVAL;
+
+ regmap_read(r, speco->sel.reg, &v);
+ *tsi = (v & speco->sel.mask) >> speco->sel.sft;
+
+ regmap_read(r, CSS_OUTPUTENABLE, &v);
+ *en = !!(v & BIT(out));
+
+ return 0;
+}
+
+/**
+ * Connect the input port and output port using CSS (Cross Stream Switch).
+ *
+ * @in : Input port number, use one of HSC_CSS_IN_*.
+ * @out : Output port number, use one of HSC_CSS_OUT_*.
+ * @en : false: Disable this path.
+ * true : Enable this path.
+ */
+int hsc_css_out_set_src(struct hsc_chip *chip, int in, int out, bool en)
+{
+ struct regmap *r = chip->regmap;
+ const struct hsc_spec_css *speco = css_out_get_spec(chip, out);
+
+ if (!css_in_is_valid(chip, in) || !speco || !speco->sel.valid)
+ return -EINVAL;
+
+ regmap_update_bits(r, speco->sel.reg, speco->sel.mask,
+ in << speco->sel.sft);
+
+ regmap_update_bits(r, CSS_OUTPUTENABLE, BIT(out), (en) ? ~0 : 0);
+
+ return 0;
+}
diff --git a/drivers/media/platform/uniphier/hsc-reg.h b/drivers/media/platform/uniphier/hsc-reg.h
index 2d87960c9b97..e5bc87658361 100644
--- a/drivers/media/platform/uniphier/hsc-reg.h
+++ b/drivers/media/platform/uniphier/hsc-reg.h
@@ -115,4 +115,33 @@
#define CDMBC_CHATPAGED(i, j) (0x3c10 + ((i) - 1) * 0x48 + (j) * 0x10)
#define CDMBC_CHATPAGEU(i, j) (0x3c14 + ((i) - 1) * 0x48 + (j) * 0x10)
+/* CSS */
+#define CSS_PTSOCONFIG 0x1c00
+#define CSS_PTSISIGNALPOL 0x1c04
+#define CSS_SIGNALPOLCH(i) (0x1c08 + (i) * 0x4)
+#define CSS_OUTPUTENABLE 0x1c10
+#define CSS_OUTPUTCTRL(i) (0x1c14 + (i) * 0x4)
+#define CSS_STSOCONFIG 0x1c2c
+#define CSS_STSOSIGNALPOL 0x1c30
+#define CSS_DMDSIGNALPOL 0x1c34
+#define CSS_PTSOSIGNALPOL 0x1c38
+#define CSS_PF0CONFIG 0x1c3c
+#define CSS_PF1CONFIG 0x1c40
+#define CSS_PFINTENABLE 0x1c44
+#define CSS_PFINTSTATUS 0x1c48
+#define CSS_AVOUTPUTCTRL(i) (0x1c4c + (i) * 0x4)
+#define CSS_DPCTRL(i) (0x1c54 + (i) * 0x4)
+#define CSS_DPCTRL_DPSEL_MASK GENMASK(22, 0)
+#define CSS_DPCTRL_DPSEL_PLAY5 BIT(15)
+#define CSS_DPCTRL_DPSEL_PLAY4 BIT(14)
+#define CSS_DPCTRL_DPSEL_PLAY3 BIT(13)
+#define CSS_DPCTRL_DPSEL_PLAY2 BIT(12)
+#define CSS_DPCTRL_DPSEL_PLAY1 BIT(11)
+#define CSS_DPCTRL_DPSEL_PLAY0 BIT(10)
+#define CSS_DPCTRL_DPSEL_TSI4 BIT(4)
+#define CSS_DPCTRL_DPSEL_TSI3 BIT(3)
+#define CSS_DPCTRL_DPSEL_TSI2 BIT(2)
+#define CSS_DPCTRL_DPSEL_TSI1 BIT(1)
+#define CSS_DPCTRL_DPSEL_TSI0 BIT(0)
+
#endif /* DVB_UNIPHIER_HSC_REG_H__ */
diff --git a/drivers/media/platform/uniphier/hsc.h b/drivers/media/platform/uniphier/hsc.h
index fddc66df81c7..1cbd17b475bf 100644
--- a/drivers/media/platform/uniphier/hsc.h
+++ b/drivers/media/platform/uniphier/hsc.h
@@ -329,6 +329,23 @@ struct hsc_conf {
int dma_out;
};
+/* CSS */
+int hsc_css_out_to_ts_in(int out);
+int hsc_css_out_to_dpll_src(int out);
+
+int hsc_dpll_get_src(struct hsc_chip *chip, int dpll, int *src);
+int hsc_dpll_set_src(struct hsc_chip *chip, int dpll, int src);
+int hsc_css_in_get_polarity(struct hsc_chip *chip, int in,
+ bool *sync_bit, bool *val_bit, bool *clk_fall);
+int hsc_css_in_set_polarity(struct hsc_chip *chip, int in,
+ bool sync_bit, bool val_bit, bool clk_fall);
+int hsc_css_out_get_polarity(struct hsc_chip *chip, int out,
+ bool *sync_bit, bool *val_bit, bool *clk_fall);
+int hsc_css_out_set_polarity(struct hsc_chip *chip, int out,
+ bool sync_bit, bool val_bit, bool clk_fall);
+int hsc_css_out_get_src(struct hsc_chip *chip, int *in, int out, bool *en);
+int hsc_css_out_set_src(struct hsc_chip *chip, int in, int out, bool en);
+
/* DMA */
u64 hsc_rb_cnt(struct hsc_dma_buf *buf);
u64 hsc_rb_cnt_to_end(struct hsc_dma_buf *buf);
--
2.18.0
This patch adds DT binding documentation for UniPhier HSC which is
MPEG2-TS input/output and demux subsystem.
Signed-off-by: Katsuhiro Suzuki <[email protected]>
---
Changes from v1:
- Fix mistakes of spelling
- Rename uniphier,hsc.txt -> socionext,uniphier-hsc.txt
---
.../bindings/media/socionext,uniphier-hsc.txt | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/socionext,uniphier-hsc.txt
diff --git a/Documentation/devicetree/bindings/media/socionext,uniphier-hsc.txt b/Documentation/devicetree/bindings/media/socionext,uniphier-hsc.txt
new file mode 100644
index 000000000000..7a91046091e2
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/socionext,uniphier-hsc.txt
@@ -0,0 +1,38 @@
+Socionext UniPhier HSC (High-speed Stream Controller)
+
+The Socionext UniPhier HSC subsystem consists of MPEG2-TS input/output and
+demultiplexer cores in the same register space.
+
+This interface supports TS serial signals (clock, valid, sync, data) from
+external demodulators.
+
+Required properties:
+- compatible : should be one of the following:
+ "socionext,uniphier-ld11-hsc"
+ "socionext,uniphier-ld20-hsc"
+- reg : offset and length of the register set for the device.
+- interrupts : should contain DMA and TSI error interrupt.
+- pinctrl-names : should be "default".
+- pinctrl-0 : defined TS serial signal pins for external demodulators.
+- clock-names : should include the following entries:
+ "hsc", "stdmac"
+- clocks : a list of phandle, should contain an entry for each
+ entry in clock-names.
+- reset-names : should include the following entries:
+ "hsc", "stdmac"
+- resets : a list of phandle, should contain an entry for each
+ entry in reset-names.
+
+Example:
+ hsc {
+ compatible = "socionext,uniphier-ld20-hsc";
+ reg = <0x5c000000 0x100000>;
+ interrupts = <0 100 4>, <0 101 4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hscin2_s>,
+ <&pinctrl_hscin3_s>;
+ clock-names = "stdmac", "hsc";
+ clocks = <&sys_clk 8>, <&sys_clk 9>;
+ reset-names = "stdmac", "hsc";
+ resets = <&sys_rst 8>, <&sys_rst 9>;
+ };
--
2.18.0
Hello Mauro,
This is ping...
> -----Original Message-----
> From: Katsuhiro Suzuki <[email protected]>
> Sent: Wednesday, August 8, 2018 2:25 PM
> To: Mauro Carvalho Chehab <[email protected]>;
> [email protected]
> Cc: Masami Hiramatsu <[email protected]>; Jassi Brar
> <[email protected]>; [email protected];
> [email protected]; Suzuki, Katsuhiro
> <[email protected]>
> Subject: [PATCH v2 0/7] add UniPhier DVB Frontend system support
>
> This series adds support for DVB Frontend system named HSC support
> for UniPhier LD11/LD20 SoCs. This driver supports MPEG2-TS serial
> signal input from external demodulator and DMA MPEG2-TS stream data
> onto memory.
>
> UniPhier HSC driver provides many ports of TS input. Since the HSC
> has mixed register map for those ports. It hard to split each register
> areas.
>
> ---
>
> Changes from v1:
> DT bindings
> - Fix mistakes of spelling
> - Rename uniphier,hsc.txt -> socionext,uniphier-hsc.txt
> Kconfig, Makefile
> - Add COMPILE_TEST, REGMAP_MMIO
> - Add $(srctree) to include path option
> Headers
> - Split large patch
> - Remove more unused definitions
> - Remove unneeded const
> - Replace enum that has special value into #define
> - Remove weird macro from register definitions
> - Remove field_get/prop inline functions
> Modules
> - Split register definitions, function prototypes
> - Fix include lines
> - Fix depended config
> - Remove redundant conditions
> - Drop adapter patches, and need no patches to build
> - Merge uniphier-adapter.o into each adapter drivers
> - Split 3 modules (core, ld11, ld20) to build adapter drivers as
> module
> - Fix compile error if build as module
> - Use hardware spec table to remove weird macro from register
> definitions
> - Use usleep_range instead of msleep
> - Use shift and mask instead of field_get/prop inline functions
>
> Katsuhiro Suzuki (7):
> media: uniphier: add DT bindings documentation for UniPhier HSC
> media: uniphier: add DMA common file of HSC
> media: uniphier: add CSS common file of HSC
> media: uniphier: add TS common file of HSC
> media: uniphier: add ucode load common file of HSC
> media: uniphier: add platform driver module of HSC
> media: uniphier: add LD11/LD20 HSC support
>
> .../bindings/media/socionext,uniphier-hsc.txt | 38 ++
> drivers/media/platform/Kconfig | 1 +
> drivers/media/platform/Makefile | 2 +
> drivers/media/platform/uniphier/Kconfig | 19 +
> drivers/media/platform/uniphier/Makefile | 5 +
> drivers/media/platform/uniphier/hsc-core.c | 515 ++++++++++++++++++
> drivers/media/platform/uniphier/hsc-css.c | 250 +++++++++
> drivers/media/platform/uniphier/hsc-dma.c | 212 +++++++
> drivers/media/platform/uniphier/hsc-ld11.c | 273 ++++++++++
> drivers/media/platform/uniphier/hsc-reg.h | 272 +++++++++
> drivers/media/platform/uniphier/hsc-ts.c | 127 +++++
> drivers/media/platform/uniphier/hsc-ucode.c | 416 ++++++++++++++
> drivers/media/platform/uniphier/hsc.h | 389 +++++++++++++
> 13 files changed, 2519 insertions(+)
> create mode 100644
> Documentation/devicetree/bindings/media/socionext,uniphier-hsc.txt
> create mode 100644 drivers/media/platform/uniphier/Kconfig
> create mode 100644 drivers/media/platform/uniphier/Makefile
> create mode 100644 drivers/media/platform/uniphier/hsc-core.c
> create mode 100644 drivers/media/platform/uniphier/hsc-css.c
> create mode 100644 drivers/media/platform/uniphier/hsc-dma.c
> create mode 100644 drivers/media/platform/uniphier/hsc-ld11.c
> create mode 100644 drivers/media/platform/uniphier/hsc-reg.h
> create mode 100644 drivers/media/platform/uniphier/hsc-ts.c
> create mode 100644 drivers/media/platform/uniphier/hsc-ucode.c
> create mode 100644 drivers/media/platform/uniphier/hsc.h
>
> --
> 2.18.0
Hi Katsuhiro-san,
Em Thu, 30 Aug 2018 10:13:11 +0900
"Katsuhiro Suzuki" <[email protected]> escreveu:
> Hello Mauro,
>
> This is ping...
Sorry for taking a long time to look into it.
Reviewing new drivers take some time, and need to be done right.
I usually let the sub-maintainers to do a first look, but they
probably missed this one. So, let me copy them. Hopefully they
can do review on it soon.
I'll try to do a review myself, but I won't be able to do it
until mid next week.
Regards,
Mauro
>
> > -----Original Message-----
> > From: Katsuhiro Suzuki <[email protected]>
> > Sent: Wednesday, August 8, 2018 2:25 PM
> > To: Mauro Carvalho Chehab <[email protected]>;
> > [email protected]
> > Cc: Masami Hiramatsu <[email protected]>; Jassi Brar
> > <[email protected]>; [email protected];
> > [email protected]; Suzuki, Katsuhiro
> > <[email protected]>
> > Subject: [PATCH v2 0/7] add UniPhier DVB Frontend system support
> >
> > This series adds support for DVB Frontend system named HSC support
> > for UniPhier LD11/LD20 SoCs. This driver supports MPEG2-TS serial
> > signal input from external demodulator and DMA MPEG2-TS stream data
> > onto memory.
> >
> > UniPhier HSC driver provides many ports of TS input. Since the HSC
> > has mixed register map for those ports. It hard to split each register
> > areas.
> >
> > ---
> >
> > Changes from v1:
> > DT bindings
> > - Fix mistakes of spelling
> > - Rename uniphier,hsc.txt -> socionext,uniphier-hsc.txt
> > Kconfig, Makefile
> > - Add COMPILE_TEST, REGMAP_MMIO
> > - Add $(srctree) to include path option
> > Headers
> > - Split large patch
> > - Remove more unused definitions
> > - Remove unneeded const
> > - Replace enum that has special value into #define
> > - Remove weird macro from register definitions
> > - Remove field_get/prop inline functions
> > Modules
> > - Split register definitions, function prototypes
> > - Fix include lines
> > - Fix depended config
> > - Remove redundant conditions
> > - Drop adapter patches, and need no patches to build
> > - Merge uniphier-adapter.o into each adapter drivers
> > - Split 3 modules (core, ld11, ld20) to build adapter drivers as
> > module
> > - Fix compile error if build as module
> > - Use hardware spec table to remove weird macro from register
> > definitions
> > - Use usleep_range instead of msleep
> > - Use shift and mask instead of field_get/prop inline functions
> >
> > Katsuhiro Suzuki (7):
> > media: uniphier: add DT bindings documentation for UniPhier HSC
> > media: uniphier: add DMA common file of HSC
> > media: uniphier: add CSS common file of HSC
> > media: uniphier: add TS common file of HSC
> > media: uniphier: add ucode load common file of HSC
> > media: uniphier: add platform driver module of HSC
> > media: uniphier: add LD11/LD20 HSC support
> >
> > .../bindings/media/socionext,uniphier-hsc.txt | 38 ++
> > drivers/media/platform/Kconfig | 1 +
> > drivers/media/platform/Makefile | 2 +
> > drivers/media/platform/uniphier/Kconfig | 19 +
> > drivers/media/platform/uniphier/Makefile | 5 +
> > drivers/media/platform/uniphier/hsc-core.c | 515 ++++++++++++++++++
> > drivers/media/platform/uniphier/hsc-css.c | 250 +++++++++
> > drivers/media/platform/uniphier/hsc-dma.c | 212 +++++++
> > drivers/media/platform/uniphier/hsc-ld11.c | 273 ++++++++++
> > drivers/media/platform/uniphier/hsc-reg.h | 272 +++++++++
> > drivers/media/platform/uniphier/hsc-ts.c | 127 +++++
> > drivers/media/platform/uniphier/hsc-ucode.c | 416 ++++++++++++++
> > drivers/media/platform/uniphier/hsc.h | 389 +++++++++++++
> > 13 files changed, 2519 insertions(+)
> > create mode 100644
> > Documentation/devicetree/bindings/media/socionext,uniphier-hsc.txt
> > create mode 100644 drivers/media/platform/uniphier/Kconfig
> > create mode 100644 drivers/media/platform/uniphier/Makefile
> > create mode 100644 drivers/media/platform/uniphier/hsc-core.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-css.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-dma.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-ld11.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-reg.h
> > create mode 100644 drivers/media/platform/uniphier/hsc-ts.c
> > create mode 100644 drivers/media/platform/uniphier/hsc-ucode.c
> > create mode 100644 drivers/media/platform/uniphier/hsc.h
> >
> > --
> > 2.18.0
>
>
>
Thanks,
Mauro
Hello Mauro,
Thank you for reviewing. Actually, I leaved Socionext at October
this year. I tried to find next person that maintain these patches
before leaving Socionext but I could not find.
And unfortunately, I cannot test and refine these DVB patches
because Socionext evaluation boards that can receive ISDB are not
sell and SoC specification is not public.
So it's better to drop my UniPhier DVB patches, I think...
Best Regards,
---
Katsuhiro Suzuki
On 2018/12/07 23:17, Mauro Carvalho Chehab wrote:
> Hi Katsuhiro-san,
>
> Em Thu, 30 Aug 2018 10:13:11 +0900
> "Katsuhiro Suzuki" <[email protected]> escreveu:
>
>> Hello Mauro,
>>
>> This is ping...
>
> Sorry for taking a long time to look into it.
>
> Reviewing new drivers take some time, and need to be done right.
>
> I usually let the sub-maintainers to do a first look, but they
> probably missed this one. So, let me copy them. Hopefully they
> can do review on it soon.
>
> I'll try to do a review myself, but I won't be able to do it
> until mid next week.
>
> Regards,
> Mauro
>
>>
>>> -----Original Message-----
>>> From: Katsuhiro Suzuki <[email protected]>
>>> Sent: Wednesday, August 8, 2018 2:25 PM
>>> To: Mauro Carvalho Chehab <[email protected]>;
>>> [email protected]
>>> Cc: Masami Hiramatsu <[email protected]>; Jassi Brar
>>> <[email protected]>; [email protected];
>>> [email protected]; Suzuki, Katsuhiro
>>> <[email protected]>
>>> Subject: [PATCH v2 0/7] add UniPhier DVB Frontend system support
>>>
>>> This series adds support for DVB Frontend system named HSC support
>>> for UniPhier LD11/LD20 SoCs. This driver supports MPEG2-TS serial
>>> signal input from external demodulator and DMA MPEG2-TS stream data
>>> onto memory.
>>>
>>> UniPhier HSC driver provides many ports of TS input. Since the HSC
>>> has mixed register map for those ports. It hard to split each register
>>> areas.
>>>
>>> ---
>>>
>>> Changes from v1:
>>> DT bindings
>>> - Fix mistakes of spelling
>>> - Rename uniphier,hsc.txt -> socionext,uniphier-hsc.txt
>>> Kconfig, Makefile
>>> - Add COMPILE_TEST, REGMAP_MMIO
>>> - Add $(srctree) to include path option
>>> Headers
>>> - Split large patch
>>> - Remove more unused definitions
>>> - Remove unneeded const
>>> - Replace enum that has special value into #define
>>> - Remove weird macro from register definitions
>>> - Remove field_get/prop inline functions
>>> Modules
>>> - Split register definitions, function prototypes
>>> - Fix include lines
>>> - Fix depended config
>>> - Remove redundant conditions
>>> - Drop adapter patches, and need no patches to build
>>> - Merge uniphier-adapter.o into each adapter drivers
>>> - Split 3 modules (core, ld11, ld20) to build adapter drivers as
>>> module
>>> - Fix compile error if build as module
>>> - Use hardware spec table to remove weird macro from register
>>> definitions
>>> - Use usleep_range instead of msleep
>>> - Use shift and mask instead of field_get/prop inline functions
>>>
>>> Katsuhiro Suzuki (7):
>>> media: uniphier: add DT bindings documentation for UniPhier HSC
>>> media: uniphier: add DMA common file of HSC
>>> media: uniphier: add CSS common file of HSC
>>> media: uniphier: add TS common file of HSC
>>> media: uniphier: add ucode load common file of HSC
>>> media: uniphier: add platform driver module of HSC
>>> media: uniphier: add LD11/LD20 HSC support
>>>
>>> .../bindings/media/socionext,uniphier-hsc.txt | 38 ++
>>> drivers/media/platform/Kconfig | 1 +
>>> drivers/media/platform/Makefile | 2 +
>>> drivers/media/platform/uniphier/Kconfig | 19 +
>>> drivers/media/platform/uniphier/Makefile | 5 +
>>> drivers/media/platform/uniphier/hsc-core.c | 515 ++++++++++++++++++
>>> drivers/media/platform/uniphier/hsc-css.c | 250 +++++++++
>>> drivers/media/platform/uniphier/hsc-dma.c | 212 +++++++
>>> drivers/media/platform/uniphier/hsc-ld11.c | 273 ++++++++++
>>> drivers/media/platform/uniphier/hsc-reg.h | 272 +++++++++
>>> drivers/media/platform/uniphier/hsc-ts.c | 127 +++++
>>> drivers/media/platform/uniphier/hsc-ucode.c | 416 ++++++++++++++
>>> drivers/media/platform/uniphier/hsc.h | 389 +++++++++++++
>>> 13 files changed, 2519 insertions(+)
>>> create mode 100644
>>> Documentation/devicetree/bindings/media/socionext,uniphier-hsc.txt
>>> create mode 100644 drivers/media/platform/uniphier/Kconfig
>>> create mode 100644 drivers/media/platform/uniphier/Makefile
>>> create mode 100644 drivers/media/platform/uniphier/hsc-core.c
>>> create mode 100644 drivers/media/platform/uniphier/hsc-css.c
>>> create mode 100644 drivers/media/platform/uniphier/hsc-dma.c
>>> create mode 100644 drivers/media/platform/uniphier/hsc-ld11.c
>>> create mode 100644 drivers/media/platform/uniphier/hsc-reg.h
>>> create mode 100644 drivers/media/platform/uniphier/hsc-ts.c
>>> create mode 100644 drivers/media/platform/uniphier/hsc-ucode.c
>>> create mode 100644 drivers/media/platform/uniphier/hsc.h
>>>
>>> --
>>> 2.18.0
>>
>>
>>
>
>
>
> Thanks,
> Mauro
>