// SPDX-License-Identifier: GPL-2.0-or-later
/* -*- linux-c -*- *
*
* ALSA driver for the digigram lx6464es interface
* low-level interface
*
* Copyright (c) 2009 Tim Blechmann <tim@klingt.org>
*/
/* #define RMH_DEBUG 1 */
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include "lx6464es.h"
#include "lx_core.h"
/* low-level register access */
static const unsigned long dsp_port_offsets[] = {
0,
0x400,
0x401,
0x402,
0x403,
0x404,
0x405,
0x406,
0x407,
0x408,
0x409,
0x40a,
0x40b,
0x40c,
0x410,
0x411,
0x412,
0x413,
0x414,
0x415,
0x416,
0x420,
0x430,
0x431,
0x432,
0x433,
0x434,
0x440
};
static void __iomem *lx_dsp_register(struct lx6464es *chip, int port)
{
void __iomem *base_address = chip->port_dsp_bar;
return base_address + dsp_port_offsets[port]*4;
}
unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port)
{
void __iomem *address = lx_dsp_register(chip, port);
return ioread32(address);
}
static void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data,
u32 len)
{
u32 __iomem *address = lx_dsp_register(chip, port);
int i;
/* we cannot use memcpy_fromio */
for (i = 0; i != len; ++i)
data[i] = ioread32(address + i);
}
void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data)
{
void __iomem *address = lx_dsp_register(chip, port);
iowrite32(data, address);
}
static void lx_dsp_reg_writebuf(struct lx6464es *chip, int port,
const u32 *data, u32 len)
{
u32 __iomem *address = lx_dsp_register(chip, port);
int i;
/* we cannot use memcpy_to */
for (i = 0; i != len; ++i)
iowrite32(data[i], address + i);
}
static const unsigned long plx_port_offsets[] = {
0x04,
0x40,
0x44,
0x48,
0x4c,
0x50,
0x54,
0x58,
0x5c,
0x64,
0x68,
0x6C
};
static void __iomem *lx_plx_register(struct lx6464es *chip, int port)
{
void __iomem *base_address = chip->port_plx_remapped;
return base_address + plx_port_offsets[port];
}
unsigned long lx_plx_reg_read(struct lx6464es *chip, int port)
{
void __iomem *address = lx_plx_register(chip, port);
return ioread32(address);
}
void lx_plx_reg_write(struct lx6464es *chip, int port, u32 data)
{
void __iomem *address = lx_plx_register(chip, port);
iowrite32(data, address);
}
/* rmh */
#ifdef CONFIG_SND_DEBUG
#define CMD_NAME(a) a
#else
#define CMD_NAME(a) NULL
#endif
#define Reg_CSM_MR 0x00000002
#define Reg_CSM_MC 0x00000001
struct dsp_cmd_info {
u32 dcCodeOp; /* Op Code of the command (usually 1st 24-bits
* word).*/
u16 dcCmdLength; /* Command length in words of 24 bits.*/
u16 dcStatusType; /* Status type: 0 for fixed length, 1 for
* random. */
u16 dcStatusLength; /* Status length (if fixed).*/
char *dcOpName;
};
/*
Initialization and control data for the Microblaze interface
- OpCode:
the opcode field of the command set at the proper offset
- CmdLength
the number of command words
- StatusType
offset in the status registers: 0 means that the return value may be
different from 0, and must be read
- StatusLength
the number of status words (in addition to the return value)
*/
static const struct dsp_cmd_info dsp_commands[] =
{
{ (CMD_00_INFO_DEBUG << OPCODE_OFFSET) , 1 /*custom*/
, 1 , 0 /**/ , CMD_NAME("INFO_DEBUG") },
{ (CMD_01_GET_SYS_CFG << OPCODE_OFFSET) , 1 /**/
, 1 , 2 /**/ , CMD_NAME("GET_SYS_CFG") },
{ (CMD_02_SET_GRANULARITY << OPCODE_OFFSET) , 1 /**/
, 1 , 0 /**/ , CMD_NAME("SET_GRANULARITY") },
{ (CMD_03_SET_TIMER_IRQ << OPCODE_OFFSET)