From patchwork Wed Aug 8 05:25:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Katsuhiro Suzuki X-Patchwork-Id: 10559539 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BA54B90E3 for ; Wed, 8 Aug 2018 05:26:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A83BA2A324 for ; Wed, 8 Aug 2018 05:26:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9ADCB2A32A; Wed, 8 Aug 2018 05:26:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4F48C2A324 for ; Wed, 8 Aug 2018 05:26:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726538AbeHHHn1 (ORCPT ); Wed, 8 Aug 2018 03:43:27 -0400 Received: from mx.socionext.com ([202.248.49.38]:4068 "EHLO mx.socionext.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726905AbeHHHn1 (ORCPT ); Wed, 8 Aug 2018 03:43:27 -0400 Received: from unknown (HELO iyokan-ex.css.socionext.com) ([172.31.9.54]) by mx.socionext.com with ESMTP; 08 Aug 2018 14:25:33 +0900 Received: from mail.mfilter.local (m-filter-2 [10.213.24.62]) by iyokan-ex.css.socionext.com (Postfix) with ESMTP id 9A543600AA; Wed, 8 Aug 2018 14:25:33 +0900 (JST) Received: from 172.31.9.53 (172.31.9.53) by m-FILTER with ESMTP; Wed, 8 Aug 2018 14:25:33 +0900 Received: from yuzu.css.socionext.com (yuzu [172.31.8.45]) by iyokan.css.socionext.com (Postfix) with ESMTP id 1C39A40372; Wed, 8 Aug 2018 14:25:33 +0900 (JST) Received: from aegis.e01.socionext.com (unknown [10.213.134.210]) by yuzu.css.socionext.com (Postfix) with ESMTP id EA7A2120448; Wed, 8 Aug 2018 14:25:32 +0900 (JST) From: Katsuhiro Suzuki To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Masami Hiramatsu , Jassi Brar , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Katsuhiro Suzuki Subject: [PATCH v2 1/7] media: uniphier: add DT bindings documentation for UniPhier HSC Date: Wed, 8 Aug 2018 14:25:13 +0900 Message-Id: <20180808052519.14528-2-suzuki.katsuhiro@socionext.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> References: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds DT binding documentation for UniPhier HSC which is MPEG2-TS input/output and demux subsystem. Signed-off-by: Katsuhiro Suzuki --- 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>; + }; From patchwork Wed Aug 8 05:25:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Katsuhiro Suzuki X-Patchwork-Id: 10559529 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F289090E3 for ; Wed, 8 Aug 2018 05:25:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DFA482A314 for ; Wed, 8 Aug 2018 05:25:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D3BA62A324; Wed, 8 Aug 2018 05:25:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 75D442A314 for ; Wed, 8 Aug 2018 05:25:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727236AbeHHHno (ORCPT ); Wed, 8 Aug 2018 03:43:44 -0400 Received: from mx.socionext.com ([202.248.49.38]:4074 "EHLO mx.socionext.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726920AbeHHHnb (ORCPT ); Wed, 8 Aug 2018 03:43:31 -0400 Received: from unknown (HELO kinkan-ex.css.socionext.com) ([172.31.9.52]) by mx.socionext.com with ESMTP; 08 Aug 2018 14:25:33 +0900 Received: from mail.mfilter.local (m-filter-2 [10.213.24.62]) by kinkan-ex.css.socionext.com (Postfix) with ESMTP id AA7C818015C; Wed, 8 Aug 2018 14:25:33 +0900 (JST) Received: from 172.31.9.53 (172.31.9.53) by m-FILTER with ESMTP; Wed, 8 Aug 2018 14:25:33 +0900 Received: from yuzu.css.socionext.com (yuzu [172.31.8.45]) by iyokan.css.socionext.com (Postfix) with ESMTP id 4927540372; Wed, 8 Aug 2018 14:25:33 +0900 (JST) Received: from aegis.e01.socionext.com (unknown [10.213.134.210]) by yuzu.css.socionext.com (Postfix) with ESMTP id 229EB120415; Wed, 8 Aug 2018 14:25:33 +0900 (JST) From: Katsuhiro Suzuki To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Masami Hiramatsu , Jassi Brar , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Katsuhiro Suzuki Subject: [PATCH v2 2/7] media: uniphier: add DMA common file of HSC Date: Wed, 8 Aug 2018 14:25:14 +0900 Message-Id: <20180808052519.14528-3-suzuki.katsuhiro@socionext.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> References: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 +#include +#include + +#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 +#include +#include + +#include +#include +#include +#include + +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__ */ From patchwork Wed Aug 8 05:25:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Katsuhiro Suzuki X-Patchwork-Id: 10559537 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A926513AC for ; Wed, 8 Aug 2018 05:26:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 956D42A314 for ; Wed, 8 Aug 2018 05:26:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 87D102A324; Wed, 8 Aug 2018 05:26:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B71D32A314 for ; Wed, 8 Aug 2018 05:26:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727081AbeHHHn3 (ORCPT ); Wed, 8 Aug 2018 03:43:29 -0400 Received: from mx.socionext.com ([202.248.49.38]:4078 "EHLO mx.socionext.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726921AbeHHHn2 (ORCPT ); Wed, 8 Aug 2018 03:43:28 -0400 Received: from unknown (HELO kinkan-ex.css.socionext.com) ([172.31.9.52]) by mx.socionext.com with ESMTP; 08 Aug 2018 14:25:33 +0900 Received: from mail.mfilter.local (m-filter-2 [10.213.24.62]) by kinkan-ex.css.socionext.com (Postfix) with ESMTP id B735E180B37; Wed, 8 Aug 2018 14:25:33 +0900 (JST) Received: from 172.31.9.53 (172.31.9.53) by m-FILTER with ESMTP; Wed, 8 Aug 2018 14:25:33 +0900 Received: from yuzu.css.socionext.com (yuzu [172.31.8.45]) by iyokan.css.socionext.com (Postfix) with ESMTP id 74DF040372; Wed, 8 Aug 2018 14:25:33 +0900 (JST) Received: from aegis.e01.socionext.com (unknown [10.213.134.210]) by yuzu.css.socionext.com (Postfix) with ESMTP id 4F307120415; Wed, 8 Aug 2018 14:25:33 +0900 (JST) From: Katsuhiro Suzuki To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Masami Hiramatsu , Jassi Brar , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Katsuhiro Suzuki Subject: [PATCH v2 3/7] media: uniphier: add CSS common file of HSC Date: Wed, 8 Aug 2018 14:25:15 +0900 Message-Id: <20180808052519.14528-4-suzuki.katsuhiro@socionext.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> References: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 +#include +#include + +#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); From patchwork Wed Aug 8 05:25:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Katsuhiro Suzuki X-Patchwork-Id: 10559535 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CB70F13AC for ; Wed, 8 Aug 2018 05:26:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B61DE2A314 for ; Wed, 8 Aug 2018 05:26:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AAF462A324; Wed, 8 Aug 2018 05:26:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C55C2A314 for ; Wed, 8 Aug 2018 05:26:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727123AbeHHHn3 (ORCPT ); Wed, 8 Aug 2018 03:43:29 -0400 Received: from mx.socionext.com ([202.248.49.38]:4068 "EHLO mx.socionext.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727039AbeHHHn2 (ORCPT ); Wed, 8 Aug 2018 03:43:28 -0400 Received: from unknown (HELO kinkan-ex.css.socionext.com) ([172.31.9.52]) by mx.socionext.com with ESMTP; 08 Aug 2018 14:25:34 +0900 Received: from mail.mfilter.local (m-filter-2 [10.213.24.62]) by kinkan-ex.css.socionext.com (Postfix) with ESMTP id 4E8ED18015C; Wed, 8 Aug 2018 14:25:34 +0900 (JST) Received: from 172.31.9.53 (172.31.9.53) by m-FILTER with ESMTP; Wed, 8 Aug 2018 14:25:34 +0900 Received: from yuzu.css.socionext.com (yuzu [172.31.8.45]) by iyokan.css.socionext.com (Postfix) with ESMTP id A07FE40372; Wed, 8 Aug 2018 14:25:33 +0900 (JST) Received: from aegis.e01.socionext.com (unknown [10.213.134.210]) by yuzu.css.socionext.com (Postfix) with ESMTP id 7B415120415; Wed, 8 Aug 2018 14:25:33 +0900 (JST) From: Katsuhiro Suzuki To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Masami Hiramatsu , Jassi Brar , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Katsuhiro Suzuki Subject: [PATCH v2 4/7] media: uniphier: add TS common file of HSC Date: Wed, 8 Aug 2018 14:25:16 +0900 Message-Id: <20180808052519.14528-5-suzuki.katsuhiro@socionext.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> References: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add TS input/output code to start/stop configure the MPEG2-TS ports of HSC for Socionext UniPhier SoCs. Signed-off-by: Katsuhiro Suzuki --- 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 +#include +#include + +#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); From patchwork Wed Aug 8 05:25:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Katsuhiro Suzuki X-Patchwork-Id: 10559533 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5540896FA for ; Wed, 8 Aug 2018 05:26:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 43E062A314 for ; Wed, 8 Aug 2018 05:26:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 386BB2A324; Wed, 8 Aug 2018 05:26:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2D1A62A314 for ; Wed, 8 Aug 2018 05:26:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727263AbeHHHny (ORCPT ); Wed, 8 Aug 2018 03:43:54 -0400 Received: from mx.socionext.com ([202.248.49.38]:4065 "EHLO mx.socionext.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726979AbeHHHn3 (ORCPT ); Wed, 8 Aug 2018 03:43:29 -0400 Received: from unknown (HELO iyokan-ex.css.socionext.com) ([172.31.9.54]) by mx.socionext.com with ESMTP; 08 Aug 2018 14:25:33 +0900 Received: from mail.mfilter.local (m-filter-1 [10.213.24.61]) by iyokan-ex.css.socionext.com (Postfix) with ESMTP id 0DF0A600AA; Wed, 8 Aug 2018 14:25:34 +0900 (JST) Received: from 172.31.9.53 (172.31.9.53) by m-FILTER with ESMTP; Wed, 8 Aug 2018 14:25:34 +0900 Received: from yuzu.css.socionext.com (yuzu [172.31.8.45]) by iyokan.css.socionext.com (Postfix) with ESMTP id CB5F640372; Wed, 8 Aug 2018 14:25:33 +0900 (JST) Received: from aegis.e01.socionext.com (unknown [10.213.134.210]) by yuzu.css.socionext.com (Postfix) with ESMTP id A6242120415; Wed, 8 Aug 2018 14:25:33 +0900 (JST) From: Katsuhiro Suzuki To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Masami Hiramatsu , Jassi Brar , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Katsuhiro Suzuki Subject: [PATCH v2 5/7] media: uniphier: add ucode load common file of HSC Date: Wed, 8 Aug 2018 14:25:17 +0900 Message-Id: <20180808052519.14528-6-suzuki.katsuhiro@socionext.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> References: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Adds code to load uCode and start the internal cores of HSC for Socionext UniPhier SoCs. Signed-off-by: Katsuhiro Suzuki --- 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 +#include +#include +#include + +#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__ */ From patchwork Wed Aug 8 05:25:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Katsuhiro Suzuki X-Patchwork-Id: 10559523 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 50BFC13AC for ; Wed, 8 Aug 2018 05:25:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3FC3B2A314 for ; Wed, 8 Aug 2018 05:25:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 33D3C2A326; Wed, 8 Aug 2018 05:25:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 28A2C2A314 for ; Wed, 8 Aug 2018 05:25:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726905AbeHHHng (ORCPT ); Wed, 8 Aug 2018 03:43:36 -0400 Received: from mx.socionext.com ([202.248.49.38]:4065 "EHLO mx.socionext.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727039AbeHHHnb (ORCPT ); Wed, 8 Aug 2018 03:43:31 -0400 Received: from unknown (HELO kinkan-ex.css.socionext.com) ([172.31.9.52]) by mx.socionext.com with ESMTP; 08 Aug 2018 14:25:34 +0900 Received: from mail.mfilter.local (m-filter-1 [10.213.24.61]) by kinkan-ex.css.socionext.com (Postfix) with ESMTP id 93A3518015C; Wed, 8 Aug 2018 14:25:34 +0900 (JST) Received: from 172.31.9.53 (172.31.9.53) by m-FILTER with ESMTP; Wed, 8 Aug 2018 14:25:34 +0900 Received: from yuzu.css.socionext.com (yuzu [172.31.8.45]) by iyokan.css.socionext.com (Postfix) with ESMTP id 030E940372; Wed, 8 Aug 2018 14:25:34 +0900 (JST) Received: from aegis.e01.socionext.com (unknown [10.213.134.210]) by yuzu.css.socionext.com (Postfix) with ESMTP id D2622120415; Wed, 8 Aug 2018 14:25:33 +0900 (JST) From: Katsuhiro Suzuki To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Masami Hiramatsu , Jassi Brar , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Katsuhiro Suzuki Subject: [PATCH v2 6/7] media: uniphier: add platform driver module of HSC Date: Wed, 8 Aug 2018 14:25:18 +0900 Message-Id: <20180808052519.14528-7-suzuki.katsuhiro@socionext.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> References: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds common platform driver module of HSC (High speed Stream Controller) driver for Socionext UniPhier SoCs. Signed-off-by: Katsuhiro Suzuki --- 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 +#include +#include +#include +#include +#include +#include +#include + +#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 "); +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__ */ From patchwork Wed Aug 8 05:25:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Katsuhiro Suzuki X-Patchwork-Id: 10559525 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CE035A65F for ; Wed, 8 Aug 2018 05:25:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BC41C2A314 for ; Wed, 8 Aug 2018 05:25:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B0B282A324; Wed, 8 Aug 2018 05:25:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 02ABE2A31B for ; Wed, 8 Aug 2018 05:25:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727167AbeHHHnb (ORCPT ); Wed, 8 Aug 2018 03:43:31 -0400 Received: from mx.socionext.com ([202.248.49.38]:4078 "EHLO mx.socionext.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726905AbeHHHna (ORCPT ); Wed, 8 Aug 2018 03:43:30 -0400 Received: from unknown (HELO kinkan-ex.css.socionext.com) ([172.31.9.52]) by mx.socionext.com with ESMTP; 08 Aug 2018 14:25:34 +0900 Received: from mail.mfilter.local (m-filter-1 [10.213.24.61]) by kinkan-ex.css.socionext.com (Postfix) with ESMTP id 9DAAB180B37; Wed, 8 Aug 2018 14:25:34 +0900 (JST) Received: from 172.31.9.53 (172.31.9.53) by m-FILTER with ESMTP; Wed, 8 Aug 2018 14:25:34 +0900 Received: from yuzu.css.socionext.com (yuzu [172.31.8.45]) by iyokan.css.socionext.com (Postfix) with ESMTP id 2DA8A40372; Wed, 8 Aug 2018 14:25:34 +0900 (JST) Received: from aegis.e01.socionext.com (unknown [10.213.134.210]) by yuzu.css.socionext.com (Postfix) with ESMTP id 093FC120415; Wed, 8 Aug 2018 14:25:34 +0900 (JST) From: Katsuhiro Suzuki To: Mauro Carvalho Chehab , linux-media@vger.kernel.org Cc: Masami Hiramatsu , Jassi Brar , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Katsuhiro Suzuki Subject: [PATCH v2 7/7] media: uniphier: add LD11/LD20 HSC support Date: Wed, 8 Aug 2018 14:25:19 +0900 Message-Id: <20180808052519.14528-8-suzuki.katsuhiro@socionext.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> References: <20180808052519.14528-1-suzuki.katsuhiro@socionext.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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), +};