Commit ba3d7ddf authored by Christian Gromm's avatar Christian Gromm Committed by Greg Kroah-Hartman

Staging: most: add MOST driver's hdm-dim2 module

This patch adds the hdm-dim2 module of the MOST driver to the kernel's
driver staging area. This module is part of the MOST driver and handles
the MediaLB interface of the MOST network interface controller.

This patch is needed in order to use the MediaLB peripheral interface of
the network interface controller.
Signed-off-by: default avatarChristian Gromm <christian.gromm@microchip.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3d31c0cb
...@@ -21,4 +21,6 @@ source "drivers/staging/most/aim-sound/Kconfig" ...@@ -21,4 +21,6 @@ source "drivers/staging/most/aim-sound/Kconfig"
source "drivers/staging/most/aim-v4l2/Kconfig" source "drivers/staging/most/aim-v4l2/Kconfig"
source "drivers/staging/most/hdm-dim2/Kconfig"
endif endif
...@@ -3,3 +3,4 @@ obj-$(CONFIG_AIM_CDEV) += aim-cdev/ ...@@ -3,3 +3,4 @@ obj-$(CONFIG_AIM_CDEV) += aim-cdev/
obj-$(CONFIG_AIM_NETWORK) += aim-network/ obj-$(CONFIG_AIM_NETWORK) += aim-network/
obj-$(CONFIG_AIM_SOUND) += aim-sound/ obj-$(CONFIG_AIM_SOUND) += aim-sound/
obj-$(CONFIG_AIM_V4L2) += aim-v4l2/ obj-$(CONFIG_AIM_V4L2) += aim-v4l2/
obj-$(CONFIG_HDM_DIM2) += hdm-dim2/
#
# MediaLB configuration
#
config HDM_DIM2
tristate "DIM2 HDM"
---help---
Say Y here if you want to connect via MediaLB to network tranceiver.
This device driver is platform dependent and needs an addtional
platform driver to be installed. For more information contact
maintainer of this driver.
To compile this driver as a module, choose M here: the
module will be called hdm_dim2.
obj-$(CONFIG_HDM_DIM2) += hdm_dim2.o
hdm_dim2-objs := dim2_hdm.o dim2_hal.o dim2_sysfs.o
ccflags-y += -Idrivers/staging/most/mostcore/
ccflags-y += -Idrivers/staging/most/aim-network/
/*
* dim2_errors.h - Definitions of errors for DIM2 HAL API
* (MediaLB, Device Interface Macro IP, OS62420)
*
* Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This file is licensed under GPLv2.
*/
#ifndef _MOST_DIM_ERRORS_H
#define _MOST_DIM_ERRORS_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* MOST DIM errors.
*/
enum dim_errors_t {
/** Not an error */
DIM_NO_ERROR = 0,
/** Bad base address for DIM2 IP */
DIM_INIT_ERR_DIM_ADDR = 0x10,
/**< Bad MediaLB clock */
DIM_INIT_ERR_MLB_CLOCK,
/** Bad channel address */
DIM_INIT_ERR_CHANNEL_ADDRESS,
/** Out of DBR memory */
DIM_INIT_ERR_OUT_OF_MEMORY,
/** DIM API is called while DIM is not initialized successfully */
DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20,
/**
* Configuration does not respect hardware limitations
* for isochronous or synchronous channels
*/
DIM_ERR_BAD_CONFIG,
/**
* Buffer size does not respect hardware limitations
* for isochronous or synchronous channels
*/
DIM_ERR_BAD_BUFFER_SIZE,
DIM_ERR_UNDERFLOW,
DIM_ERR_OVERFLOW,
};
#ifdef __cplusplus
}
#endif
#endif /* _MOST_DIM_ERRORS_H */
This diff is collapsed.
/*
* dim2_hal.h - DIM2 HAL interface
* (MediaLB, Device Interface Macro IP, OS62420)
*
* Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This file is licensed under GPLv2.
*/
#ifndef _DIM2_HAL_H
#define _DIM2_HAL_H
#include <linux/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* The values below are specified in the hardware specification.
* So, they should not be changed until the hardware specification changes.
*/
enum mlb_clk_speed {
CLK_256FS = 0,
CLK_512FS = 1,
CLK_1024FS = 2,
CLK_2048FS = 3,
CLK_3072FS = 4,
CLK_4096FS = 5,
CLK_6144FS = 6,
CLK_8192FS = 7,
};
struct dim_ch_state_t {
bool ready; /* Shows readiness to enqueue next buffer */
u16 done_buffers; /* Number of completed buffers */
};
typedef int atomic_counter_t;
struct int_ch_state {
/* changed only in interrupt context */
volatile atomic_counter_t request_counter;
/* changed only in task context */
volatile atomic_counter_t service_counter;
u8 idx1;
u8 idx2;
u8 level; /* [0..2], buffering level */
};
struct dim_channel {
struct int_ch_state state;
u8 addr;
u16 dbr_addr;
u16 dbr_size;
u16 packet_length; /*< Isochronous packet length in bytes. */
u16 bytes_per_frame; /*< Synchronous bytes per frame. */
u16 done_sw_buffers_number; /*< Done software buffers number. */
};
u8 DIM_Startup(void *dim_base_address, u32 mlb_clock);
void DIM_Shutdown(void);
bool DIM_GetLockState(void);
u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size);
u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length);
u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame);
u8 DIM_InitControl(struct dim_channel *ch, u8 is_tx, u16 ch_address,
u16 max_buffer_size);
u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
u16 max_buffer_size);
u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
u16 packet_length);
u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
u16 bytes_per_frame);
u8 DIM_DestroyChannel(struct dim_channel *ch);
void DIM_ServiceIrq(struct dim_channel *const *channels);
u8 DIM_ServiceChannel(struct dim_channel *ch);
struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
struct dim_ch_state_t *dim_ch_state_ptr);
bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr,
u16 buffer_size);
bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number);
u32 DIM_ReadRegister(u8 register_index);
extern u32 DIMCB_IoRead(u32 *ptr32);
extern void DIMCB_IoWrite(u32 *ptr32, u32 value);
extern void DIMCB_OnError(u8 error_id, const char *error_message);
extern void DIMCB_OnFail(const char *filename, int linenum);
#ifdef __cplusplus
}
#endif
#endif /* _DIM2_HAL_H */
This diff is collapsed.
/*
* dim2_hdm.h - MediaLB DIM2 HDM Header
*
* Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This file is licensed under GPLv2.
*/
#ifndef DIM2_HDM_H
#define DIM2_HDM_H
struct device;
/* platform dependent data for dim2 interface */
struct dim2_platform_data {
int (*init)(struct dim2_platform_data *pd, void *io_base, int clk_speed);
void (*destroy)(struct dim2_platform_data *pd);
void *priv;
};
#endif /* DIM2_HDM_H */
/*
* dim2_reg.h - Definitions for registers of DIM2
* (MediaLB, Device Interface Macro IP, OS62420)
*
* Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This file is licensed under GPLv2.
*/
#ifndef DIM2_OS62420_H
#define DIM2_OS62420_H
#include <linux/types.h>
#ifdef __cplusplus
extern "C" {
#endif
struct dim2_regs {
/* 0x00 */ u32 MLBC0;
/* 0x01 */ u32 rsvd0[1];
/* 0x02 */ u32 MLBPC0;
/* 0x03 */ u32 MS0;
/* 0x04 */ u32 rsvd1[1];
/* 0x05 */ u32 MS1;
/* 0x06 */ u32 rsvd2[2];
/* 0x08 */ u32 MSS;
/* 0x09 */ u32 MSD;
/* 0x0A */ u32 rsvd3[1];
/* 0x0B */ u32 MIEN;
/* 0x0C */ u32 rsvd4[1];
/* 0x0D */ u32 MLBPC2;
/* 0x0E */ u32 MLBPC1;
/* 0x0F */ u32 MLBC1;
/* 0x10 */ u32 rsvd5[0x10];
/* 0x20 */ u32 HCTL;
/* 0x21 */ u32 rsvd6[1];
/* 0x22 */ u32 HCMR0;
/* 0x23 */ u32 HCMR1;
/* 0x24 */ u32 HCER0;
/* 0x25 */ u32 HCER1;
/* 0x26 */ u32 HCBR0;
/* 0x27 */ u32 HCBR1;
/* 0x28 */ u32 rsvd7[8];
/* 0x30 */ u32 MDAT0;
/* 0x31 */ u32 MDAT1;
/* 0x32 */ u32 MDAT2;
/* 0x33 */ u32 MDAT3;
/* 0x34 */ u32 MDWE0;
/* 0x35 */ u32 MDWE1;
/* 0x36 */ u32 MDWE2;
/* 0x37 */ u32 MDWE3;
/* 0x38 */ u32 MCTL;
/* 0x39 */ u32 MADR;
/* 0x3A */ u32 rsvd8[0xB6];
/* 0xF0 */ u32 ACTL;
/* 0xF1 */ u32 rsvd9[3];
/* 0xF4 */ u32 ACSR0;
/* 0xF5 */ u32 ACSR1;
/* 0xF6 */ u32 ACMR0;
/* 0xF7 */ u32 ACMR1;
};
#define DIM2_MASK(n) (~((~(u32)0)<<(n)))
enum {
MLBC0_MLBLK_BIT = 7,
MLBC0_MLBPEN_BIT = 5,
MLBC0_MLBCLK_SHIFT = 2,
MLBC0_MLBCLK_VAL_256FS = 0,
MLBC0_MLBCLK_VAL_512FS = 1,
MLBC0_MLBCLK_VAL_1024FS = 2,
MLBC0_MLBCLK_VAL_2048FS = 3,
MLBC0_FCNT_SHIFT = 15,
MLBC0_FCNT_MASK = 7,
MLBC0_FCNT_VAL_1FPSB = 0,
MLBC0_FCNT_VAL_2FPSB = 1,
MLBC0_FCNT_VAL_4FPSB = 2,
MLBC0_FCNT_VAL_8FPSB = 3,
MLBC0_FCNT_VAL_16FPSB = 4,
MLBC0_FCNT_VAL_32FPSB = 5,
MLBC0_FCNT_VAL_64FPSB = 6,
MLBC0_MLBEN_BIT = 0,
MIEN_CTX_BREAK_BIT = 29,
MIEN_CTX_PE_BIT = 28,
MIEN_CTX_DONE_BIT = 27,
MIEN_CRX_BREAK_BIT = 26,
MIEN_CRX_PE_BIT = 25,
MIEN_CRX_DONE_BIT = 24,
MIEN_ATX_BREAK_BIT = 22,
MIEN_ATX_PE_BIT = 21,
MIEN_ATX_DONE_BIT = 20,
MIEN_ARX_BREAK_BIT = 19,
MIEN_ARX_PE_BIT = 18,
MIEN_ARX_DONE_BIT = 17,
MIEN_SYNC_PE_BIT = 16,
MIEN_ISOC_BUFO_BIT = 1,
MIEN_ISOC_PE_BIT = 0,
MLBC1_NDA_SHIFT = 8,
MLBC1_NDA_MASK = 0xFF,
MLBC1_CLKMERR_BIT = 7,
MLBC1_LOCKERR_BIT = 6,
ACTL_DMA_MODE_BIT = 2,
ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0,
ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1,
ACTL_SCE_BIT = 0,
HCTL_EN_BIT = 15
};
enum {
CDT1_BS_ISOC_SHIFT = 0,
CDT1_BS_ISOC_MASK = DIM2_MASK(9),
CDT3_BD_SHIFT = 0,
CDT3_BD_MASK = DIM2_MASK(12),
CDT3_BD_ISOC_MASK = DIM2_MASK(13),
CDT3_BA_SHIFT = 16,
ADT0_CE_BIT = 15,
ADT0_LE_BIT = 14,
ADT0_PG_BIT = 13,
ADT1_RDY_BIT = 15,
ADT1_DNE_BIT = 14,
ADT1_ERR_BIT = 13,
ADT1_PS_BIT = 12,
ADT1_MEP_BIT = 11,
ADT1_BD_SHIFT = 0,
ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),
CAT_MFE_BIT = 14,
CAT_MT_BIT = 13,
CAT_RNW_BIT = 12,
CAT_CE_BIT = 11,
CAT_CT_SHIFT = 8,
CAT_CT_VAL_SYNC = 0,
CAT_CT_VAL_CONTROL = 1,
CAT_CT_VAL_ASYNC = 2,
CAT_CT_VAL_ISOC = 3,
CAT_CL_SHIFT = 0,
CAT_CL_MASK = DIM2_MASK(6)
};
#ifdef __cplusplus
}
#endif
#endif /* DIM2_OS62420_H */
/*
* dim2_sysfs.c - MediaLB sysfs information
*
* Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This file is licensed under GPLv2.
*/
/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include "dim2_sysfs.h"
struct bus_attr {
struct attribute attr;
ssize_t (*show)(struct medialb_bus *bus, char *buf);
ssize_t (*store)(struct medialb_bus *bus, const char *buf, size_t count);
};
static ssize_t state_show(struct medialb_bus *bus, char *buf)
{
bool state = dim2_sysfs_get_state_cb();
return sprintf(buf, "%s\n", state ? "locked" : "");
}
static struct bus_attr state_attr = __ATTR_RO(state);
static struct attribute *bus_default_attrs[] = {
&state_attr.attr,
NULL,
};
static struct attribute_group bus_attr_group = {
.attrs = bus_default_attrs,
};
static void bus_kobj_release(struct kobject *kobj)
{
}
static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct medialb_bus *bus =
container_of(kobj, struct medialb_bus, kobj_group);
struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
if (!xattr->show)
return -EIO;
return xattr->show(bus, buf);
}
static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
ssize_t ret;
struct medialb_bus *bus =
container_of(kobj, struct medialb_bus, kobj_group);
struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
if (!xattr->store)
return -EIO;
ret = xattr->store(bus, buf, count);
return ret;
}
static struct sysfs_ops const bus_kobj_sysfs_ops = {
.show = bus_kobj_attr_show,
.store = bus_kobj_attr_store,
};
static struct kobj_type bus_ktype = {
.release = bus_kobj_release,
.sysfs_ops = &bus_kobj_sysfs_ops,
};
int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
{
int err;
kobject_init(&bus->kobj_group, &bus_ktype);
err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
if (err) {
pr_err("kobject_add() failed: %d\n", err);
goto err_kobject_add;
}
err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
if (err) {
pr_err("sysfs_create_group() failed: %d\n", err);
goto err_create_group;
}
return 0;
err_create_group:
kobject_put(&bus->kobj_group);
err_kobject_add:
return err;
}
void dim2_sysfs_destroy(struct medialb_bus *bus)
{
kobject_put(&bus->kobj_group);
}
/*
* dim2_sysfs.h - MediaLB sysfs information
*
* Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This file is licensed under GPLv2.
*/
/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
#ifndef DIM2_SYSFS_H
#define DIM2_SYSFS_H
#include <linux/kobject.h>
struct medialb_bus {
struct kobject kobj_group;
};
struct dim2_hdm;
int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj);
void dim2_sysfs_destroy(struct medialb_bus *bus);
/*
* callback,
* must deliver MediaLB state as true if locked or false if unlocked
*/
bool dim2_sysfs_get_state_cb(void);
#endif /* DIM2_SYSFS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment